source: trunk/gsdl/src/recpt/browsetools.cpp@ 1610

Last change on this file since 1610 was 1610, checked in by paynter, 24 years ago

Changed the formatstring parser in formattools so that an {If} macro (which
has the form {If}{decision,then,else}) can branch on any text, not just on
metadata. This means you can use extra cgi arguments and macros like
_cgiargmode_ to display documents in different modes and switch between
them. To accomplish all this, the formattools class needed to be able to
evaluate macros (through displayclass), so the other files have been
changed to pass in a displayclass object.

  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 19.1 KB
Line 
1
2/**********************************************************************
3 *
4 * browsetools.cpp --
5 * Copyright (C) 1999 The New Zealand Digital Library Project
6 *
7 * A component of the Greenstone digital library software
8 * from the New Zealand Digital Library Project at the
9 * University of Waikato, New Zealand.
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 *
25 *********************************************************************/
26
27#include "browsetools.h"
28#include "OIDtools.h"
29
30
31// output_controls displays the detach, expand/contract contents,
32// expand/contract text and highlighting/no highlighting buttons
33
34void output_controls (cgiargsclass &args, const text_tarray &ibuttons,
35 recptproto * /*collectproto*/, displayclass &disp,
36 outconvertclass &outconvert, ostream &textout,
37 ostream &/*logout*/) {
38
39 if (args["u"] != "1") {
40
41 FilterResponse_t response;
42 text_tarray metadata;
43 text_tarray buttons;
44
45 text_tarray::const_iterator here = ibuttons.begin();
46 text_tarray::const_iterator end = ibuttons.end();
47
48 while (here != end) {
49
50 if (*here == "Detach")
51 buttons.push_back ("_document:imagedetach_");
52 else if (*here == "Highlight") {
53 if (args["hl"] == "1")
54 buttons.push_back ("_document:imagenohighlight_");
55 else
56 buttons.push_back ("_document:imagehighlight_");
57 } else if (*here == "Expand Contents") {
58 if (args["gc"] == "1")
59 buttons.push_back ("_document:imagecontracttoc_");
60 else
61 buttons.push_back ("_document:imageexpandtoc_");
62 } else if (*here == "Expand Text") {
63 if (args.getintarg("gt"))
64 buttons.push_back ("_document:imagecontracttext_");
65 else
66 buttons.push_back ("_document:imageexpandtext_");
67 }
68 here ++;
69 }
70
71 here = buttons.begin();
72 end = buttons.end();
73 int count = 0;
74 while (here != end) {
75 if ((count != 0) && ((count % 2) == 0)) textout << "<br>\n";
76 textout << outconvert << disp << *here;
77 count ++;
78 here ++;
79 }
80 }
81}
82
83
84// at the moment this just writes out the html to display
85// the cover image (assuming it's called cover.jpg)
86// this whole thing should be done with a call to the collection
87// server which would send a link to the cover image if there
88// was one otherwise send title, author and stuff
89void output_cover_image (cgiargsclass &args, recptproto * /*collectproto*/,
90 displayclass &disp, outconvertclass &outconvert,
91 ostream &textout, ostream &/*logout*/) {
92
93 if (args["d"].empty()) return;
94
95 textout << outconvert << disp <<
96 "<img src=\"_httpcollimg_/_thisOID_/cover.jpg\"><br>\n";
97}
98
99void output_titles (cgiargsclass &args, recptproto *collectproto,
100 formatinfo_t &formatinfo, displayclass &disp,
101 outconvertclass &outconvert, ostream &textout,
102 ostream &logout) {
103
104 if (args["d"].empty()) return;
105
106 text_tset metadata;
107 bool getParents;
108 FilterResponse_t response;
109
110 format_t *formatlistptr = new format_t();
111 parse_formatstring (formatinfo.DocumentHeading, formatlistptr, metadata, getParents);
112
113 if (!get_info (args["d"], args["c"], metadata, getParents, collectproto, response, logout))
114 return;
115
116 textout << outconvert << disp
117 << get_formatted_string (args["c"],collectproto,
118 response.docInfo[0], disp, formatlistptr,
119 logout);
120}
121
122
123static void recurse_contents (ResultDocInfo_t &section, cgiargsclass &args, bool fulltoc,
124 browserclass *bptr, text_tset &metadata, bool &getParents,
125 format_t *formatlistptr, format_tmap &formatlistmap,
126 formatinfo_t &formatinfo, browsermapclass *browsermap,
127 int tabcount, recptproto *collectproto, displayclass &disp,
128 outconvertclass &outconvert, ostream &textout, ostream &logout) {
129 text_t formatstring;
130
131 bool is_classify = false;
132 if (args["d"].empty() || fulltoc) is_classify = true;
133
134 // output this section
135 bool use_table = is_table_content (formatlistptr);
136 tabcount += bptr->output_section_group (section, args, "", tabcount, formatlistptr, use_table,
137 metadata, getParents, collectproto, disp, outconvert,
138 textout, logout);
139
140 text_t classification;
141 if (!is_classify) classification = "Document";
142 else get_top (args["cl"], classification);
143
144 int haschildren = section.metadata["haschildren"].values[0].getint();
145 const text_t &doctype = section.metadata["doctype"].values[0];
146 text_t classifytype = section.metadata["childtype"].values[0];
147 // HLists and DateLists are displayed as VLists when contents
148 // are expanded, Paged documents are displayed as HLists
149 if (classifytype == "HList" || classifytype == "DateList") classifytype = "VList";
150 if (classifytype == "Paged") classifytype = "HList";
151
152 // recurse through children
153 if ((haschildren == 1) && (!is_classify || fulltoc || doctype == "classify")) {
154
155 // get browser for displaying children
156 bptr = browsermap->getbrowser (classifytype);
157 bptr->load_metadata_defaults (metadata);
158
159 // get the formatstring if there is one
160 if (!get_formatstring (classification, classifytype,
161 formatinfo.formatstrings, formatstring))
162 formatstring = bptr->get_default_formatstring();
163
164 format_tmap::const_iterator it = formatlistmap.find (formatstring);
165 // check if formatlistptr is cached
166 if (it != formatlistmap.end()) formatlistptr = (*it).second;
167 else {
168 formatlistptr = new format_t();
169 parse_formatstring (formatstring, formatlistptr, metadata, getParents);
170 formatlistmap[formatstring] = formatlistptr;
171 }
172
173 FilterResponse_t tmp;
174 get_children (section.OID, args["c"], metadata, getParents, collectproto, tmp, logout);
175 ResultDocInfo_tarray::iterator thisdoc = tmp.docInfo.begin();
176 ResultDocInfo_tarray::iterator lastdoc = tmp.docInfo.end();
177
178 while (thisdoc != lastdoc) {
179 recurse_contents (*thisdoc, args, fulltoc, bptr, metadata, getParents,
180 formatlistptr, formatlistmap, formatinfo, browsermap,
181 tabcount, collectproto, disp, outconvert, textout, logout);
182 thisdoc ++;
183 }
184 }
185}
186
187
188// expanded_contents recurses through all contents. there's a special case
189// for an HList when contents are expanded (i.e. it's displayed as a VList)
190//
191// if we're inside a document we expand all contents from the top,
192// if we're at classification level we'll just expand out those contents below
193// the current one
194
195void expanded_contents (cgiargsclass &args, int tabcount, bool fulltoc,
196 browsermapclass *browsermap, formatinfo_t &formatinfo,
197 recptproto *collectproto, displayclass &disp,
198 outconvertclass &outconvert, ostream &textout,
199 ostream &logout) {
200
201 if (args["d"].empty() && args["cl"].empty()) return;
202 text_t OID;
203
204 FilterResponse_t response;
205 bool getParents = false;
206 text_tset metadata;
207 text_t classifytype, classification, formatstring;
208
209 if (!args["d"].empty()) {
210 // document level
211 if (fulltoc) {
212 get_top (args["cl"], OID);
213 classification = OID;
214 }
215 else {
216 // always expand document level from top
217 get_top (args["d"], OID);
218 classification = "Document";
219 }
220 } else {
221 // classification level
222 OID = args["cl"];
223 get_top (args["cl"], classification);
224 }
225
226 // get classifytype of this level
227 text_t tOID;
228 if (is_top(OID)) {
229 classifytype = "thistype";
230 tOID = OID;
231 } else {
232 classifytype = "childtype";
233 tOID = get_parent (OID);
234 }
235 metadata.insert (classifytype);
236
237 if (!get_info (tOID, args["c"], metadata, getParents, collectproto, response, logout))
238 return;
239 classifytype = response.docInfo[0].metadata[classifytype].values[0];
240 // if we still don't have a classifytype we'll use the default
241 if (classifytype.empty()) {
242 browserclass *bptr = browsermap->get_default_browser ();
243 classifytype = bptr->get_browser_name ();
244 }
245
246 // HLists are displayed as VLists when contents are expanded,
247 // Paged documents are displayed as HLists
248 if (classifytype == "HList") {
249 classifytype = "VList";
250 text_t pOID = get_parent (OID);
251 if (!pOID.empty()) {
252 OID = pOID;
253 // this is assuming that top levels are always 'Invisible' !!!
254 if (is_top (OID)) classifytype = "Invisible";
255 }
256 }
257 if (classifytype == "Paged") classifytype = "HList";
258
259 metadata.erase (metadata.begin(), metadata.end());
260
261 // metadata elements needed by recurse_contents
262 metadata.insert ("childtype");
263 metadata.insert ("doctype");
264 metadata.insert ("haschildren");
265
266 // load up metadata array with browser defaults
267 browserclass *bptr = browsermap->getbrowser (classifytype);
268 bptr->load_metadata_defaults (metadata);
269
270 // get the formatstring if there is one or use the browsers default
271 if (!get_formatstring (classification, classifytype,
272 formatinfo.formatstrings, formatstring))
273 formatstring = bptr->get_default_formatstring();
274
275 format_t *formatlistptr = new format_t();
276 parse_formatstring (formatstring, formatlistptr, metadata, getParents);
277
278 // protocol call
279 if (!get_info (OID, args["c"], metadata, getParents, collectproto, response, logout))
280 return;
281
282 format_tmap formatlistmap;
283 formatlistmap[formatstring] = formatlistptr;
284
285 recurse_contents (response.docInfo[0], args, fulltoc, bptr, metadata,
286 getParents, formatlistptr, formatlistmap, formatinfo, browsermap,
287 tabcount, collectproto, disp, outconvert, textout, logout);
288
289 // clean up format list pointers
290 format_tmap::const_iterator here = formatlistmap.begin();
291 format_tmap::const_iterator end = formatlistmap.end();
292 while (here != end) {
293 delete (*here).second;
294 here ++;
295 }
296}
297
298
299static void load_formatstring (const text_t &classifytype, text_tset &metadata,
300 bool &getParents, const text_t &classification,
301 browsermapclass *browsermap, formatinfo_t &formatinfo,
302 format_tmap &formatlistmap) {
303 text_t formatstring;
304
305 // load up metadata array with browser defaults
306 browserclass *bptr = browsermap->getbrowser (classifytype);
307 bptr->load_metadata_defaults (metadata);
308
309 // get the formatstring if there is one or use the browsers default
310 if (!get_formatstring (classification, classifytype,
311 formatinfo.formatstrings, formatstring))
312 formatstring = bptr->get_default_formatstring();
313
314 // see if it's cached
315 format_tmap::const_iterator it = formatlistmap.find (formatstring);
316 if (it == formatlistmap.end()) {
317 format_t *formatlistptr = new format_t();
318 parse_formatstring (formatstring, formatlistptr, metadata, getParents);
319 formatlistmap[formatstring] = formatlistptr;
320 }
321}
322
323static void load_formatstrings (FilterResponse_t &response, text_tset &metadata,
324 bool &getParents, const text_t &classification,
325 browsermapclass *browsermap, formatinfo_t &formatinfo,
326 format_tmap &formatlistmap) {
327
328 text_tset cache;
329
330 ResultDocInfo_tarray::iterator thisdoc = response.docInfo.begin();
331 ResultDocInfo_tarray::iterator lastdoc = response.docInfo.end();
332
333 while (thisdoc != lastdoc) {
334
335 if (is_top ((*thisdoc).OID))
336 load_formatstring ((*thisdoc).metadata["thistype"].values[0], metadata,
337 getParents, classification, browsermap, formatinfo,
338 formatlistmap);
339
340 text_t &childtype = (*thisdoc).metadata["childtype"].values[0];
341 text_tset::const_iterator it = cache.find (childtype);
342 if (it == cache.end()) {
343 load_formatstring (childtype, metadata, getParents, classification,
344 browsermap, formatinfo, formatlistmap);
345 cache.insert (childtype);
346 }
347 thisdoc ++;
348 }
349}
350
351static void output_parents (FilterResponse_t &response, cgiargsclass &args,
352 browsermapclass *browsermap, formatinfo_t &formatinfo,
353 format_tmap &formatlistmap, const text_t &classification,
354 int &tabcount, text_tset &metadata, bool &getParents,
355 recptproto *collectproto, displayclass &disp,
356 outconvertclass &outconvert, ostream &textout,
357 ostream &logout) {
358
359 format_t *formatlistptr = NULL;
360 text_t classifytype, formatstring;
361 bool use_table, first = true;
362 ResultDocInfo_tarray::iterator thisparent = response.docInfo.begin();
363 ResultDocInfo_tarray::iterator lastparent = response.docInfo.end();
364 while (thisparent != lastparent) {
365
366 // get classifytype of this level
367 if (is_top ((*thisparent).OID)) classifytype = (*thisparent).metadata["thistype"].values[0];
368 else if (!first) classifytype = (*(thisparent-1)).metadata["childtype"].values[0];
369
370 // if we still don't have a classifytype we'll use the default
371 if (classifytype.empty()) {
372 browserclass *bptr = browsermap->get_default_browser ();
373 classifytype = bptr->get_browser_name ();
374 }
375
376 browserclass *bptr = browsermap->getbrowser (classifytype);
377
378 // get the formatstring if there is one or use the browsers default
379 if (!get_formatstring (classification, classifytype,
380 formatinfo.formatstrings, formatstring))
381 formatstring = bptr->get_default_formatstring();
382
383 // see if it's cached
384 format_tmap::const_iterator it = formatlistmap.find (formatstring);
385 if (it != formatlistmap.end()) formatlistptr = (*it).second;
386 else {
387 logout << "browsetools error\n";
388 return;
389 }
390
391 use_table = is_table_content (formatlistptr);
392 tabcount += bptr->output_section_group (*thisparent, args, "", tabcount, formatlistptr,
393 use_table, metadata, getParents, collectproto,
394 disp, outconvert, textout, logout);
395 first = false;
396 thisparent ++;
397 }
398}
399
400void contracted_contents (cgiargsclass &args, int tabcount, bool fulltoc,
401 browsermapclass *browsermap, formatinfo_t &formatinfo,
402 recptproto *collectproto, displayclass &disp,
403 outconvertclass &outconvert, ostream &textout,
404 ostream &logout) {
405
406 FilterResponse_t response;
407 text_tset metadata;
408 bool getParents = false;
409 text_t formatstring;
410 text_tarray parents;
411 text_t OID = args["d"];
412 text_t classification = "Document";
413 if (OID.empty()) {
414 OID = args["cl"];
415 get_top (OID, classification);
416 } else if (fulltoc)
417 get_top (args["cl"], classification);
418
419 bool haschildren = has_children (OID, args["c"], collectproto, logout);
420
421 if ((!args["d"].empty()) && fulltoc)
422 get_parents_array (args["cl"] + ".fc", parents);
423 if (haschildren) get_parents_array (OID + ".fc", parents);
424 else get_parents_array (OID, parents);
425
426 if (!parents.empty()) {
427 // get classifytypes of each parent
428 metadata.insert ("thistype");
429 metadata.insert ("childtype");
430
431 if (!get_info (parents, args["c"], metadata, getParents, collectproto, response, logout))
432 return;
433
434 // get formatstrings for all parents
435 format_tmap formatlistmap;
436 load_formatstrings (response, metadata, getParents, classification,
437 browsermap, formatinfo, formatlistmap);
438
439 if (!get_info (parents, args["c"], metadata, getParents, collectproto, response, logout))
440 return;
441
442 // display each parent
443 output_parents (response, args, browsermap, formatinfo, formatlistmap,
444 classification, tabcount, metadata, getParents,
445 collectproto, disp, outconvert, textout, logout);
446
447 metadata.erase (metadata.begin(), metadata.end());
448
449 // clean up cached format list pointers
450 format_tmap::const_iterator here = formatlistmap.begin();
451 format_tmap::const_iterator end = formatlistmap.end();
452 while (here != end) {
453 delete (*here).second;
454 here ++;
455 }
456 }
457
458 // get childrens classifytype
459 text_t classifytype;
460 int numparents = response.docInfo.size();
461 if (!parents.empty())
462 classifytype = response.docInfo[numparents-1].metadata["childtype"].values[0];
463 else {
464 // use the default
465 browserclass *bptr = browsermap->get_default_browser ();
466 classifytype = bptr->get_browser_name ();
467 }
468
469 // load up metadata array with browser defaults
470 browserclass *bptr = browsermap->getbrowser (classifytype);
471 bptr->load_metadata_defaults (metadata);
472
473 // get the formatstring if there is one or use the browsers default
474 if (!get_formatstring (classification, classifytype,
475 formatinfo.formatstrings, formatstring))
476 formatstring = bptr->get_default_formatstring();
477
478 format_t *formatlistptr = new format_t();
479 parse_formatstring (formatstring, formatlistptr, metadata, getParents);
480
481 if (haschildren)
482 get_children (OID, args["c"], metadata, getParents,
483 collectproto, response, logout);
484 else if (!is_top(OID)) {
485 get_children (OID + ".pr", args["c"], metadata, getParents,
486 collectproto, response, logout);
487 haschildren = true;
488 }
489
490 // display children
491 if (haschildren) {
492 bool use_table = is_table_content (formatlistptr);
493 // collection used to be "" // **** // check with Stef!!!!
494 bptr->output_section_group (response, args, args["c"], tabcount, formatlistptr, use_table,
495 metadata, getParents, collectproto, disp, outconvert,
496 textout, logout);
497 }
498
499 delete formatlistptr;
500}
501
502void output_toc (cgiargsclass &args, browsermapclass *browsermap,
503 formatinfo_t &formatinfo, recptproto *collectproto,
504 displayclass &disp, outconvertclass &outconvert,
505 ostream &textout, ostream &logout) {
506
507 int tabcount = 0;
508 bool havecontrols = false;
509 bool fulltoc = false;
510
511 if (args["cl"] != "search") {
512 // see if there's a FullTOC string
513 text_t cl_top, full_toc;
514 get_top (args["cl"], cl_top);
515 if (get_formatstring (cl_top, "FullTOC", formatinfo.formatstrings, full_toc))
516 if (full_toc == "true") fulltoc = true;
517 }
518
519 // get the cover image (if there is one) and the control buttons
520 // if we're inside a book
521 if ((!fulltoc) && (!args["d"].empty())) {
522 textout << "<center>\n";
523 textout << outconvert << disp << "<p><table width=_pagewidth_ cellpadding=0 cellspacing=0><tr>\n";
524 textout << "<td valign=top align=left";
525 if (formatinfo.DocumentContents) textout << " width=200>\n";
526 else textout << " width=100%>\n";
527 if (formatinfo.DocumentImages)
528 output_cover_image (args, collectproto, disp, outconvert, textout, logout);
529 else if (formatinfo.DocumentTitles)
530 output_titles (args, collectproto, formatinfo, disp, outconvert, textout, logout);
531 output_controls (args, formatinfo.DocumentButtons, collectproto, disp,
532 outconvert, textout, logout);
533 textout << "</td><td valign=top>\n";
534 havecontrols = true;
535 }
536
537 if (formatinfo.DocumentContents || args["d"].empty()) {
538 if (args.getintarg("gc") == 1) {
539
540 // expanded table of contents
541 expanded_contents (args, tabcount, fulltoc, browsermap, formatinfo,
542 collectproto, disp, outconvert, textout, logout);
543 } else {
544
545 // contracted table of contents
546 contracted_contents (args, tabcount, fulltoc, browsermap, formatinfo,
547 collectproto, disp, outconvert, textout, logout);
548 }
549 }
550
551 if (havecontrols) textout << "</td></tr></table></center>\n";
552}
Note: See TracBrowser for help on using the repository browser.