/********************************************************************** * * 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"; textout << outconvert << disp << "

\n" << "\n" << "\n" << "\n" << "
\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 << "

\n"; } }