/**********************************************************************
*
* browsetools.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: browsetools.cpp 778 1999-11-09 02:28:47Z sjboddie $
*
*********************************************************************/
/*
$Log$
Revision 1.34 1999/11/09 02:28:47 sjboddie
fixed minor bug in expanded contents
Revision 1.33 1999/10/30 22:22:26 sjboddie
added collection argument to browserclass output_section_group
functions -- moved table functions to formattools
Revision 1.32 1999/10/24 07:22:37 sjboddie
added a FullTOC option
Revision 1.31 1999/10/20 03:54:20 sjboddie
problem with expanded contents
Revision 1.30 1999/10/19 21:36:59 sjboddie
fixed bug in DocumentContents
Revision 1.29 1999/10/19 08:40:12 sjboddie
fixed some stupid compiler warnings on windows
Revision 1.28 1999/10/18 20:08:36 sjboddie
tidied up a few things
Revision 1.27 1999/10/15 03:31:42 sjboddie
oops, left out an '&'
Revision 1.26 1999/10/14 22:58:05 sjboddie
finished up on changes to browseing support - may still need some
tidying up
Revision 1.25 1999/10/10 08:14:04 sjboddie
- metadata now returns mp rather than array
- redesigned browsing support (although it's not finished so
won't currently work ;-)
Revision 1.24 1999/09/28 01:46:55 rjmcnab
removed some unused stuff
Revision 1.23 1999/09/23 10:09:17 sjboddie
made some changes so AZLists within other classifications are
handled properly
Revision 1.22 1999/09/07 23:06:58 rjmcnab
removed some compiler warnings.
Revision 1.21 1999/09/07 04:56:52 sjboddie
added GPL notice
Revision 1.20 1999/08/25 04:46:58 sjboddie
fixed bug
Revision 1.19 1999/08/13 04:18:04 sjboddie
fixed some typos
Revision 1.18 1999/08/10 22:42:21 sjboddie
added more format options to document tocs - there are now just two
types of toc - standard (Hierarchical) and document (as in books)
Revision 1.17 1999/08/09 02:12:07 sjboddie
made it so dates may be only 4 digits (i.e. year only)
Revision 1.16 1999/07/30 02:16:10 sjboddie
-added ability to display nested classifications (expanded versions
of nested classifications has yet to be done).
-changed set_arrow_macros slightly to fit in with new showtoppage
format option
Revision 1.15 1999/07/21 05:01:56 sjboddie
wrote handler for DateList classification
Revision 1.14 1999/07/20 02:58:15 sjboddie
got List and AZList classifications using format strings - tidied
up a bit
Revision 1.13 1999/07/07 05:44:25 sjboddie
Made some changes to allow for new way classifiers work (i.e. you can
now have classifiers containing other classifiers). At present there's
only a special case for dealing with the hdl 'magazine' section. A bit
of a redesign is needed to get it completely flexible
Revision 1.12 1999/07/01 03:47:49 rjmcnab
Fixed a small warning.
Revision 1.11 1999/06/27 21:49:01 sjboddie
fixed a couple of version conflicts - tidied up some small things
Revision 1.10 1999/06/26 01:07:21 rjmcnab
Fixed a small "bug" -- well I probably just covered another one...
Revision 1.9 1999/06/24 05:12:15 sjboddie
lots of small changes
Revision 1.8 1999/06/17 03:06:53 sjboddie
got detach button working properly - the close book icon is now disabled
when page is detached as the javascript close() function I was using is
too unreliable over different browsers
note that in my last comment I meant the "cl" arg (not the "c" arg).
Revision 1.7 1999/06/16 23:53:14 sjboddie
tidied a few things up. documentaction::define_external_macros now
resets the "c" arg if it's set to something stupid by the .xx suffixes
Revision 1.6 1999/06/16 04:03:47 sjboddie
Now sets "cl" arg to "search" when going to a document from a search
results page. This allows the close book icon (in hierarchy toc) to
take you back to the results page if that's where you came from.
If you got to the document page somehow other than from a
classification or a search (i.e. if "cl" isn't set) then the close
book icon is disabled
Revision 1.5 1999/06/16 03:11:25 sjboddie
get_info() now takes a getParents argument
Revision 1.4 1999/05/10 03:40:26 sjboddie
lots of changes - slowly getting document action sorted out
Revision 1.3 1999/04/30 01:59:39 sjboddie
lots of stuff - getting documentaction working (documentaction replaces
old browseaction)
Revision 1.2 1999/03/29 02:14:29 sjboddie
More changes to browseaction
Revision 1.1 1999/03/25 03:10:15 sjboddie
new library for browse stuff
*/
#include "browsetools.h"
#include "OIDtools.h"
// 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_tarray metadata;
text_tarray buttons;
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") {
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") {
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 << "
\n";
textout << outconvert << disp << *here;
count ++;
here ++;
}
}
}
// at the moment this just writes out the html to display
// the cover image (assuming it's called cover.jpg)
// this whole thing should be done with a call to the collection
// server which would send a link to the cover image if there
// was one otherwise send title, author and stuff
static void output_cover_image (cgiargsclass &args, recptproto * /*collectproto*/,
displayclass &disp, outconvertclass &outconvert,
ostream &textout, ostream &/*logout*/) {
if (args["d"].empty()) return;
textout << outconvert << disp <<
"
\n";
}
static void output_titles (cgiargsclass &args, recptproto *collectproto,
formatinfo_t &formatinfo, displayclass &disp,
outconvertclass &outconvert, ostream &textout,
ostream &logout) {
if (args["d"].empty()) return;
text_tset metadata;
bool getParents;
FilterResponse_t response;
format_t *formatlistptr = new format_t();
parse_formatstring (formatinfo.DocumentHeading, formatlistptr, metadata, getParents);
if (!get_info (args["d"], args["c"], metadata, getParents, collectproto, response, logout))
return;
textout << outconvert << disp << get_formatted_string (response.docInfo[0], formatlistptr);
}
static void recurse_contents (ResultDocInfo_t §ion, cgiargsclass &args, bool fulltoc,
browserclass *bptr, text_tset &metadata, bool &getParents,
format_t *formatlistptr, format_tmap &formatlistmap,
formatinfo_t &formatinfo, browsermapclass *browsermap,
int tabcount, recptproto *collectproto, displayclass &disp,
outconvertclass &outconvert, ostream &textout, ostream &logout) {
text_t formatstring;
bool is_classify = false;
if (args["d"].empty() || fulltoc) is_classify = true;
// output this section
bool use_table = is_table_content (formatlistptr);
tabcount += bptr->output_section_group (section, args, "", tabcount, formatlistptr, use_table,
metadata, getParents, collectproto, disp, outconvert,
textout, logout);
text_t classification;
if (!is_classify) classification = "Document";
else get_top (args["cl"], classification);
int haschildren = section.metadata["haschildren"].values[0].getint();
const text_t &doctype = section.metadata["doctype"].values[0];
text_t classifytype = section.metadata["childtype"].values[0];
// HLists and DateLists are displayed as VLists when contents
// are expanded, Paged documents are displayed as HLists
if (classifytype == "HList" || classifytype == "DateList") classifytype = "VList";
if (classifytype == "Paged") classifytype = "HList";
// recurse through children
if ((haschildren == 1) && (!is_classify || fulltoc || doctype == "classify")) {
// get browser for displaying children
bptr = browsermap->getbrowser (classifytype);
bptr->load_metadata_defaults (metadata);
// get the formatstring if there is one
if (!get_formatstring (classification, classifytype,
formatinfo.formatstrings, formatstring))
formatstring = bptr->get_default_formatstring();
format_tmap::const_iterator it = formatlistmap.find (formatstring);
// check if formatlistptr is cached
if (it != formatlistmap.end()) formatlistptr = (*it).second;
else {
formatlistptr = new format_t();
parse_formatstring (formatstring, formatlistptr, metadata, getParents);
formatlistmap[formatstring] = formatlistptr;
}
FilterResponse_t tmp;
get_children (section.OID, args["c"], metadata, getParents, collectproto, tmp, logout);
ResultDocInfo_tarray::iterator thisdoc = tmp.docInfo.begin();
ResultDocInfo_tarray::iterator lastdoc = tmp.docInfo.end();
while (thisdoc != lastdoc) {
recurse_contents (*thisdoc, args, fulltoc, bptr, metadata, getParents,
formatlistptr, formatlistmap, formatinfo, browsermap,
tabcount, collectproto, disp, outconvert, textout, logout);
thisdoc ++;
}
}
}
// expanded_contents recurses through all contents. there's a special case
// for an HList when contents are expanded (i.e. it's displayed as a VList)
//
// if we're inside a document we expand all contents from the top,
// if we're at classification level we'll just expand out those contents below
// the current one
static void expanded_contents (cgiargsclass &args, int tabcount, bool fulltoc,
browsermapclass *browsermap, formatinfo_t &formatinfo,
recptproto *collectproto, displayclass &disp,
outconvertclass &outconvert, ostream &textout,
ostream &logout) {
if (args["d"].empty() && args["cl"].empty()) return;
text_t OID;
FilterResponse_t response;
bool getParents = false;
text_tset metadata;
text_t classifytype, classification, formatstring;
if (!args["d"].empty()) {
// document level
if (fulltoc) {
get_top (args["cl"], OID);
classification = OID;
}
else {
// always expand document level from top
get_top (args["d"], OID);
classification = "Document";
}
} else {
// classification level
OID = args["cl"];
get_top (args["cl"], classification);
}
// get classifytype of this level
text_t tOID;
if (is_top(OID)) {
classifytype = "thistype";
tOID = OID;
} else {
classifytype = "childtype";
tOID = get_parent (OID);
}
metadata.insert (classifytype);
if (!get_info (tOID, args["c"], metadata, getParents, collectproto, response, logout))
return;
classifytype = response.docInfo[0].metadata[classifytype].values[0];
// if we still don't have a classifytype we'll use the default
if (classifytype.empty()) {
browserclass *bptr = browsermap->get_default_browser ();
classifytype = bptr->get_browser_name ();
}
// HLists are displayed as VLists when contents are expanded,
// Paged documents are displayed as HLists
if (classifytype == "HList") {
classifytype = "VList";
text_t pOID = get_parent (OID);
if (!pOID.empty()) {
OID = pOID;
// this is assuming that top levels are always 'Invisible' !!!
if (is_top (OID)) classifytype = "Invisible";
}
}
if (classifytype == "Paged") classifytype = "HList";
metadata.erase (metadata.begin(), metadata.end());
// metadata elements needed by recurse_contents
metadata.insert ("childtype");
metadata.insert ("doctype");
metadata.insert ("haschildren");
// load up metadata array with browser defaults
browserclass *bptr = browsermap->getbrowser (classifytype);
bptr->load_metadata_defaults (metadata);
// get the formatstring if there is one or use the browsers default
if (!get_formatstring (classification, classifytype,
formatinfo.formatstrings, formatstring))
formatstring = bptr->get_default_formatstring();
format_t *formatlistptr = new format_t();
parse_formatstring (formatstring, formatlistptr, metadata, getParents);
// protocol call
if (!get_info (OID, args["c"], metadata, getParents, collectproto, response, logout))
return;
format_tmap formatlistmap;
formatlistmap[formatstring] = formatlistptr;
recurse_contents (response.docInfo[0], args, fulltoc, bptr, metadata,
getParents, formatlistptr, formatlistmap, formatinfo, browsermap,
tabcount, collectproto, disp, outconvert, textout, logout);
// clean up format list pointers
format_tmap::const_iterator here = formatlistmap.begin();
format_tmap::const_iterator end = formatlistmap.end();
while (here != end) {
delete (*here).second;
here ++;
}
}
static void load_formatstring (const text_t &classifytype, text_tset &metadata,
bool &getParents, const text_t &classification,
browsermapclass *browsermap, formatinfo_t &formatinfo,
format_tmap &formatlistmap) {
text_t formatstring;
// load up metadata array with browser defaults
browserclass *bptr = browsermap->getbrowser (classifytype);
bptr->load_metadata_defaults (metadata);
// get the formatstring if there is one or use the browsers default
if (!get_formatstring (classification, classifytype,
formatinfo.formatstrings, formatstring))
formatstring = bptr->get_default_formatstring();
// see if it's cached
format_tmap::const_iterator it = formatlistmap.find (formatstring);
if (it == formatlistmap.end()) {
format_t *formatlistptr = new format_t();
parse_formatstring (formatstring, formatlistptr, metadata, getParents);
formatlistmap[formatstring] = formatlistptr;
}
}
static void load_formatstrings (FilterResponse_t &response, text_tset &metadata,
bool &getParents, const text_t &classification,
browsermapclass *browsermap, formatinfo_t &formatinfo,
format_tmap &formatlistmap) {
text_tset cache;
ResultDocInfo_tarray::iterator thisdoc = response.docInfo.begin();
ResultDocInfo_tarray::iterator lastdoc = response.docInfo.end();
while (thisdoc != lastdoc) {
if (is_top ((*thisdoc).OID))
load_formatstring ((*thisdoc).metadata["thistype"].values[0], metadata,
getParents, classification, browsermap, formatinfo,
formatlistmap);
text_t &childtype = (*thisdoc).metadata["childtype"].values[0];
text_tset::const_iterator it = cache.find (childtype);
if (it == cache.end()) {
load_formatstring (childtype, metadata, getParents, classification,
browsermap, formatinfo, formatlistmap);
cache.insert (childtype);
}
thisdoc ++;
}
}
static void output_parents (FilterResponse_t &response, cgiargsclass &args,
browsermapclass *browsermap, formatinfo_t &formatinfo,
format_tmap &formatlistmap, const text_t &classification,
int &tabcount, text_tset &metadata, bool &getParents,
recptproto *collectproto, displayclass &disp,
outconvertclass &outconvert, ostream &textout,
ostream &logout) {
format_t *formatlistptr = NULL;
text_t classifytype, formatstring;
bool use_table, first = true;
ResultDocInfo_tarray::iterator thisparent = response.docInfo.begin();
ResultDocInfo_tarray::iterator lastparent = response.docInfo.end();
while (thisparent != lastparent) {
// get classifytype of this level
if (is_top ((*thisparent).OID)) classifytype = (*thisparent).metadata["thistype"].values[0];
else if (!first) classifytype = (*(thisparent-1)).metadata["childtype"].values[0];
// if we still don't have a classifytype we'll use the default
if (classifytype.empty()) {
browserclass *bptr = browsermap->get_default_browser ();
classifytype = bptr->get_browser_name ();
}
browserclass *bptr = browsermap->getbrowser (classifytype);
// get the formatstring if there is one or use the browsers default
if (!get_formatstring (classification, classifytype,
formatinfo.formatstrings, formatstring))
formatstring = bptr->get_default_formatstring();
// see if it's cached
format_tmap::const_iterator it = formatlistmap.find (formatstring);
if (it != formatlistmap.end()) formatlistptr = (*it).second;
else {
logout << "browsetools error\n";
return;
}
use_table = is_table_content (formatlistptr);
tabcount += bptr->output_section_group (*thisparent, args, "", tabcount, formatlistptr,
use_table, metadata, getParents, collectproto,
disp, outconvert, textout, logout);
first = false;
thisparent ++;
}
}
static void contracted_contents (cgiargsclass &args, int tabcount, bool fulltoc,
browsermapclass *browsermap, formatinfo_t &formatinfo,
recptproto *collectproto, displayclass &disp,
outconvertclass &outconvert, ostream &textout,
ostream &logout) {
FilterResponse_t response;
text_tset metadata;
bool getParents = false;
text_t formatstring;
text_tarray parents;
text_t OID = args["d"];
text_t classification = "Document";
if (OID.empty()) {
OID = args["cl"];
get_top (OID, classification);
} else if (fulltoc)
get_top (args["cl"], classification);
bool haschildren = has_children (OID, args["c"], collectproto, logout);
if ((!args["d"].empty()) && fulltoc)
get_parents_array (args["cl"] + ".fc", parents);
if (haschildren) get_parents_array (OID + ".fc", parents);
else get_parents_array (OID, parents);
if (!parents.empty()) {
// get classifytypes of each parent
metadata.insert ("thistype");
metadata.insert ("childtype");
if (!get_info (parents, args["c"], metadata, getParents, collectproto, response, logout))
return;
// get formatstrings for all parents
format_tmap formatlistmap;
load_formatstrings (response, metadata, getParents, classification,
browsermap, formatinfo, formatlistmap);
if (!get_info (parents, args["c"], metadata, getParents, collectproto, response, logout))
return;
// display each parent
output_parents (response, args, browsermap, formatinfo, formatlistmap,
classification, tabcount, metadata, getParents,
collectproto, disp, outconvert, textout, logout);
metadata.erase (metadata.begin(), metadata.end());
// clean up cached format list pointers
format_tmap::const_iterator here = formatlistmap.begin();
format_tmap::const_iterator end = formatlistmap.end();
while (here != end) {
delete (*here).second;
here ++;
}
}
// get childrens classifytype
text_t classifytype;
int numparents = response.docInfo.size();
if (!parents.empty())
classifytype = response.docInfo[numparents-1].metadata["childtype"].values[0];
else {
// use the default
browserclass *bptr = browsermap->get_default_browser ();
classifytype = bptr->get_browser_name ();
}
// load up metadata array with browser defaults
browserclass *bptr = browsermap->getbrowser (classifytype);
bptr->load_metadata_defaults (metadata);
// get the formatstring if there is one or use the browsers default
if (!get_formatstring (classification, classifytype,
formatinfo.formatstrings, formatstring))
formatstring = bptr->get_default_formatstring();
format_t *formatlistptr = new format_t();
parse_formatstring (formatstring, formatlistptr, metadata, getParents);
if (haschildren)
get_children (OID, args["c"], metadata, getParents,
collectproto, response, logout);
else
get_children (OID + ".pr", args["c"], metadata, getParents,
collectproto, response, logout);
// display children
bool use_table = is_table_content (formatlistptr);
bptr->output_section_group (response, args, "", tabcount, formatlistptr, use_table,
metadata, getParents, collectproto, disp, outconvert,
textout, logout);
delete formatlistptr;
}
void output_toc (cgiargsclass &args, browsermapclass *browsermap,
formatinfo_t &formatinfo, recptproto *collectproto,
displayclass &disp, outconvertclass &outconvert,
ostream &textout, ostream &logout) {
int tabcount = 0;
bool havecontrols = false;
bool fulltoc = false;
if (args["cl"] != "search") {
// see if there's a FullTOC string
text_t cl_top, full_toc;
get_top (args["cl"], cl_top);
if (get_formatstring (cl_top, "FullTOC", formatinfo.formatstrings, full_toc))
if (full_toc == "true") fulltoc = true;
}
// get the cover image (if there is one) and the control buttons
// if we're inside a book
if ((!fulltoc) && (!args["d"].empty())) {
textout << "
\n"; else textout << " width=100%>\n"; if (formatinfo.DocumentImages) output_cover_image (args, collectproto, disp, outconvert, textout, logout); else if (formatinfo.DocumentTitles) output_titles (args, collectproto, formatinfo, disp, outconvert, textout, logout); output_controls (args, formatinfo.DocumentButtons, collectproto, disp, outconvert, textout, logout); textout << " | \n"; havecontrols = true; } if (formatinfo.DocumentContents || args["d"].empty()) { if (args.getintarg("gc") == 1) { // expanded table of contents expanded_contents (args, tabcount, fulltoc, browsermap, formatinfo, collectproto, disp, outconvert, textout, logout); } else { // contracted table of contents contracted_contents (args, tabcount, fulltoc, browsermap, formatinfo, collectproto, disp, outconvert, textout, logout); } } if (havecontrols) textout << " |