/**********************************************************************
*
* 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.
*
*
*********************************************************************/
#include "browsetools.h"
#include "OIDtools.h"
// output_controls displays the detach, expand/contract contents,
// expand/contract text and highlighting/no highlighting buttons
void output_controls (cgiargsclass &args, const text_tarray &ibuttons,
recptproto *collectproto, displayclass &disp,
outconvertclass &outconvert, ostream &textout,
ostream &logout) {
FilterResponse_t response;
text_tset metadata;
metadata.insert("pdf");
if (!get_info (args["d"], args["c"], metadata, false, collectproto, response, logout)) return;
if (!response.docInfo[0].metadata["pdf"].values[0].empty()) {
textout << outconvert << disp << "_document:imagepagepdf_";
}
text_t top;
get_top (args["d"], top);
if (!get_info (top, args["c"], metadata, false, collectproto, response, logout)) return;
if (!response.docInfo[0].metadata["pdf"].values[0].empty()) {
textout << outconvert << disp << "_document:imagearticlepdf_";
}
textout << outconvert << disp
<< "_document:imagedetach_";
if (args["hl"] == "1") {
textout << outconvert << disp << "_document:imagenohighlight_";
} else {
textout << outconvert << disp << "_document:imagehighlight_";
}
}
// 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
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";
}
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 (args["c"],collectproto,
response.docInfo[0], disp, formatlistptr,
logout);
}
//this function outputs the related documents in the format specified
//in the collection configuration file if the collection preferences
//indicate they wish related documents to be displayed.
void output_related_docs (cgiargsclass &args, recptproto *collectproto,
formatinfo_t &formatinfo, displayclass &disp,
outconvertclass &outconvert, ostream &textout,
ostream &logout) {
if (args["d"].empty()) return; //if no OID
if (args["rd"] != "1") return; //if preferences say no related documents
text_tset metadata;
bool getParents;
FilterResponse_t response;
//create new format pointer and parse the related doc format
//string specified in the collection config file
format_t *formatlistptr = new format_t();
parse_formatstring (formatinfo.RelatedDocuments, formatlistptr, metadata, getParents);
if (!get_info (args["d"], args["c"], metadata, getParents, collectproto, response, logout))
return;
//get the format string from formattools.cpp
text_t relateddocs = get_formatted_string (args["c"],collectproto, response.docInfo[0],
disp, formatlistptr, logout);
//output the related documents
textout << outconvert << disp << relateddocs;
}
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
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 ++;
}
}
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 we're not outputting the TOC for a valid OID, then we should be giving
// the TOC of a classification
if (OID.empty()) {
OID = args["cl"];
get_top (OID, classification);
}
// if we're to give the full TOC of a document, get the parent for the whole
// document now
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 if (!is_top(OID)) {
get_children (OID + ".pr", args["c"], metadata, getParents,
collectproto, response, logout);
haschildren = true;
}
// display children
if (haschildren) {
bool use_table = is_table_content (formatlistptr);
// collection used to be "" // **** // check with Stef!!!!
bptr->output_section_group (response, args, args["c"], tabcount, formatlistptr, use_table,
metadata, getParents, collectproto, disp, outconvert,
textout, logout);
}
delete formatlistptr;
}
/**
* This function outputs contents of a classifier to the reader
* including parent levels
*/
void expand_show_contents (cgiargsclass &args, int tabcount, bool fulltoc,
browsermapclass *browsermap, formatinfo_t &formatinfo,
recptproto *collectproto, displayclass &disp,
outconvertclass &outconvert, ostream &textout,
ostream &logout)
{
int coloffset = 0;
text_tarray parents;
FilterResponse_t response;
text_t OID = args["d"];
if (OID.empty()) OID = args["cl"];
bool haschildren = has_children (OID, args["c"], collectproto, logout);
// get parents list
if (!is_top(OID)) get_parents_array (OID, parents);
if (args["d"].empty() || haschildren || parents.empty())
parents.push_back(OID);
// if inside a book top title is needed
if (!args["d"].empty()) {
coloffset = 1;
text_t classification, classifytype, formatstring, topOID = parents[0];
text_tset metadata;
format_t *formatlistptr = new format_t();
bool use_table, getParents = false;
get_top (args["cl"], classification);
// getting information about top OID
metadata.insert ("thistype");
get_info ( topOID, args["c"], metadata, getParents, collectproto, response, logout);
if (!response.docInfo[0].metadata["thistype"].values.empty())
classifytype = response.docInfo[0].metadata["thistype"].values[0];
browserclass *bptr = browsermap->getbrowser (classifytype);
if (classifytype.empty()) {
bptr = browsermap->get_default_browser();
}
// 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();
parse_formatstring (formatstring, formatlistptr, metadata, getParents);
metadata.insert ("doctype");
metadata.insert ("haschildren");
get_info (topOID, args["c"], metadata, getParents, collectproto, response, logout);
// ouput top OID section
use_table = is_table_content (formatlistptr);
bptr->output_section_group (response.docInfo[0], args, "", tabcount, formatlistptr, use_table,
metadata, getParents, collectproto, disp, outconvert, textout, logout);
}
recurse_contents_levels (parents, args, coloffset, tabcount, fulltoc, browsermap,
formatinfo, collectproto, disp, outconvert, textout, logout);
textout << "\n";
}
void recurse_contents_levels (text_tarray &parents,
cgiargsclass &args, int coloffset, 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;
text_t OID, formatstring, classification, classifytype;;
bool use_table, getParents = false;
int haschildren = 0;
format_t *formatlistptr = new format_t();
// display children for last level
if (tabcount == (parents.size() - 1)) {
logout << "@@@lastlevel@@@\n";
// setting metadata fields
metadata.insert ("thistype");
metadata.insert ("childtype");
metadata.insert ("haschildren");
OID = parents[tabcount];
get_info (OID, args["c"], metadata, getParents, collectproto, response, logout);
get_top (OID, classification);
if (!response.docInfo.empty())
haschildren = response.docInfo[0].metadata["haschildren"].values[0].getint();
// get childrens classifytype
if (!response.docInfo.empty())
classifytype = response.docInfo[0].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();
parse_formatstring (formatstring, formatlistptr, metadata, getParents);
if (haschildren)
get_children (OID, args["c"], metadata, getParents,
collectproto, response, logout);
else if (!is_top(OID)) {
get_children (OID + ".pr", args["c"], metadata, getParents,
collectproto, response, logout);
haschildren = true;
}
// display children
if (haschildren) {
use_table = is_table_content (formatlistptr);
bptr->output_section_group (response, args, args["c"], coloffset + tabcount, formatlistptr, use_table,
metadata, getParents, collectproto, disp, outconvert,
textout, logout);
}
} else {
text_t pOID;
OID = parents[tabcount];
get_top (OID, classification);
// load metadata fields
metadata.insert ("thistype");
metadata.insert ("childtype");
metadata.insert ("haschildren");
metadata.insert ("doctype");
if (tabcount) pOID = parents[tabcount-1];
else pOID = OID;
get_info (pOID, args["c"], metadata, getParents, collectproto, response, logout);
// get classifytype of this level
if (is_top (pOID)) classifytype = response.docInfo[0].metadata["childtype"].values[0];
else classifytype = response.docInfo[0].metadata["thistype"].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();
// parse format string
parse_formatstring (formatstring, formatlistptr, metadata, getParents);
use_table = is_table_content (formatlistptr);
get_children (OID, args["c"], metadata, getParents, collectproto, response, logout);
ResultDocInfo_tarray::iterator thissibling = response.docInfo.begin();
ResultDocInfo_tarray::iterator lastsibling = response.docInfo.end();
while (thissibling != lastsibling) {
logout << "@@@level:@@@" << tabcount << "\n";
bptr->output_section_group (*thissibling, args, args["c"], coloffset + tabcount, formatlistptr,
use_table, metadata, getParents, collectproto,
disp, outconvert, textout, logout);
if ((*thissibling).OID == parents[tabcount+1]) {
recurse_contents_levels (parents, args, coloffset, tabcount+1, fulltoc, browsermap,
formatinfo, collectproto, disp, outconvert,textout, logout);
}
thissibling ++;
}
}
delete formatlistptr;
}
/**
* This function outputs the contents of a classifier list to the reader -
* the document will in fact be empty, so this does the "real" output
*/
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"; output_titles (args, collectproto, formatinfo, 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 if (args.getintarg("gc") == 2) { // expand visible levels of table of contents expand_show_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 << " |
\n"; output_controls (args, formatinfo.DocumentButtons, collectproto, disp, outconvert, textout, logout); textout << " |