/********************************************************************** * * 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"; 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 << "
\n"; }