source: main/tags/2.10/gsdl/src/recpt/browsetools.cpp@ 30242

Last change on this file since 30242 was 688, checked in by sjboddie, 25 years ago

oops, left out an '&'

  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 22.3 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 * $Id: browsetools.cpp 688 1999-10-15 03:31:42Z sjboddie $
26 *
27 *********************************************************************/
28
29/*
30 $Log$
31 Revision 1.27 1999/10/15 03:31:42 sjboddie
32 oops, left out an '&'
33
34 Revision 1.26 1999/10/14 22:58:05 sjboddie
35 finished up on changes to browseing support - may still need some
36 tidying up
37
38 Revision 1.25 1999/10/10 08:14:04 sjboddie
39 - metadata now returns mp rather than array
40 - redesigned browsing support (although it's not finished so
41 won't currently work ;-)
42
43 Revision 1.24 1999/09/28 01:46:55 rjmcnab
44 removed some unused stuff
45
46 Revision 1.23 1999/09/23 10:09:17 sjboddie
47 made some changes so AZLists within other classifications are
48 handled properly
49
50 Revision 1.22 1999/09/07 23:06:58 rjmcnab
51 removed some compiler warnings.
52
53 Revision 1.21 1999/09/07 04:56:52 sjboddie
54 added GPL notice
55
56 Revision 1.20 1999/08/25 04:46:58 sjboddie
57 fixed bug
58
59 Revision 1.19 1999/08/13 04:18:04 sjboddie
60 fixed some typos
61
62 Revision 1.18 1999/08/10 22:42:21 sjboddie
63 added more format options to document tocs - there are now just two
64 types of toc - standard (Hierarchical) and document (as in books)
65
66 Revision 1.17 1999/08/09 02:12:07 sjboddie
67 made it so dates may be only 4 digits (i.e. year only)
68
69 Revision 1.16 1999/07/30 02:16:10 sjboddie
70 -added ability to display nested classifications (expanded versions
71 of nested classifications has yet to be done).
72 -changed set_arrow_macros slightly to fit in with new showtoppage
73 format option
74
75 Revision 1.15 1999/07/21 05:01:56 sjboddie
76 wrote handler for DateList classification
77
78 Revision 1.14 1999/07/20 02:58:15 sjboddie
79 got List and AZList classifications using format strings - tidied
80 up a bit
81
82 Revision 1.13 1999/07/07 05:44:25 sjboddie
83 Made some changes to allow for new way classifiers work (i.e. you can
84 now have classifiers containing other classifiers). At present there's
85 only a special case for dealing with the hdl 'magazine' section. A bit
86 of a redesign is needed to get it completely flexible
87
88 Revision 1.12 1999/07/01 03:47:49 rjmcnab
89 Fixed a small warning.
90
91 Revision 1.11 1999/06/27 21:49:01 sjboddie
92 fixed a couple of version conflicts - tidied up some small things
93
94 Revision 1.10 1999/06/26 01:07:21 rjmcnab
95 Fixed a small "bug" -- well I probably just covered another one...
96
97 Revision 1.9 1999/06/24 05:12:15 sjboddie
98 lots of small changes
99
100 Revision 1.8 1999/06/17 03:06:53 sjboddie
101 got detach button working properly - the close book icon is now disabled
102 when page is detached as the javascript close() function I was using is
103 too unreliable over different browsers
104 note that in my last comment I meant the "cl" arg (not the "c" arg).
105
106 Revision 1.7 1999/06/16 23:53:14 sjboddie
107 tidied a few things up. documentaction::define_external_macros now
108 resets the "c" arg if it's set to something stupid by the .xx suffixes
109
110 Revision 1.6 1999/06/16 04:03:47 sjboddie
111 Now sets "cl" arg to "search" when going to a document from a search
112 results page. This allows the close book icon (in hierarchy toc) to
113 take you back to the results page if that's where you came from.
114 If you got to the document page somehow other than from a
115 classification or a search (i.e. if "cl" isn't set) then the close
116 book icon is disabled
117
118 Revision 1.5 1999/06/16 03:11:25 sjboddie
119 get_info() now takes a getParents argument
120
121 Revision 1.4 1999/05/10 03:40:26 sjboddie
122 lots of changes - slowly getting document action sorted out
123
124 Revision 1.3 1999/04/30 01:59:39 sjboddie
125 lots of stuff - getting documentaction working (documentaction replaces
126 old browseaction)
127
128 Revision 1.2 1999/03/29 02:14:29 sjboddie
129
130 More changes to browseaction
131
132 Revision 1.1 1999/03/25 03:10:15 sjboddie
133
134 new library for browse stuff
135
136 */
137
138#include "browsetools.h"
139#include "OIDtools.h"
140
141
142// simply checks to see if formatstring begins with a <td> tag
143static bool is_table_content (const text_t &formatstring) {
144 text_t::const_iterator here = formatstring.begin();
145 text_t::const_iterator end = formatstring.end();
146
147 while (here != end) {
148 if (*here != ' ') {
149 if (*here == '<') {
150 if ((*(here+1) == 't' || *(here+1) == 'T') &&
151 (*(here+2) == 'd' || *(here+2) == 'D') &&
152 (*(here+3) == '>' || *(here+3) == ' '))
153 return true;
154 } else return false;
155 }
156 here ++;
157 }
158 return false;
159}
160
161static bool is_table_content (const format_t *formatlistptr) {
162
163 if (formatlistptr == NULL) return false;
164
165 if (formatlistptr->command == comText)
166 return is_table_content (formatlistptr->text);
167
168 return false;
169}
170
171// output_controls displays the detach, expand/contract contents,
172// expand/contract text and highlighting/no highlighting buttons
173static void output_controls (cgiargsclass &args, const text_tarray &ibuttons,
174 recptproto * /*collectproto*/, displayclass &disp,
175 outconvertclass &outconvert, ostream &textout,
176 ostream &/*logout*/) {
177
178 if (args["u"] != "1") {
179
180 FilterResponse_t response;
181 text_tarray metadata;
182 text_tarray buttons;
183
184 text_tarray::const_iterator here = ibuttons.begin();
185 text_tarray::const_iterator end = ibuttons.end();
186
187 while (here != end) {
188
189 if (*here == "Detach")
190 buttons.push_back ("_document:imagedetach_");
191 else if (*here == "Highlight") {
192 if (args["hl"] == "1")
193 buttons.push_back ("_document:imagenohighlight_");
194 else
195 buttons.push_back ("_document:imagehighlight_");
196 } else if (*here == "Expand Contents") {
197 if (args["gc"] == "1")
198 buttons.push_back ("_document:imagecontracttoc_");
199 else
200 buttons.push_back ("_document:imageexpandtoc_");
201 } else if (*here == "Expand Text") {
202 if (args.getintarg("gt"))
203 buttons.push_back ("_document:imagecontracttext_");
204 else
205 buttons.push_back ("_document:imageexpandtext_");
206 }
207 here ++;
208 }
209
210 here = buttons.begin();
211 end = buttons.end();
212 int count = 0;
213 while (here != end) {
214 if ((count != 0) && ((count % 3) == 0)) textout << "<br>\n";
215 textout << outconvert << disp << *here;
216 count ++;
217 here ++;
218 }
219 }
220}
221
222
223// at the moment this just writes out the html to display
224// the cover image (assuming it's called cover.jpg)
225// this whole thing should be done with a call to the collection
226// server which would send a link to the cover image if there
227// was one otherwise send title, author and stuff
228static void output_cover_image (cgiargsclass &args, recptproto */*collectproto*/,
229 displayclass &disp, outconvertclass &outconvert,
230 ostream &textout, ostream &/*logout*/) {
231
232 if (args["d"].empty()) return;
233
234 textout << outconvert << disp <<
235 "<img src=\"_httpcollection_/archives/_thisOID_/cover.jpg\"><br>\n";
236}
237
238static void output_titles (cgiargsclass &args, recptproto *collectproto,
239 formatinfo_t &formatinfo, displayclass &disp,
240 outconvertclass &outconvert, ostream &textout,
241 ostream &logout) {
242
243 if (args["d"].empty()) return;
244
245 text_tset metadata;
246 bool getParents;
247 FilterResponse_t response;
248
249 format_t *formatlistptr = new format_t();
250 parse_formatstring (formatinfo.DocumentHeading, formatlistptr, metadata, getParents);
251
252 text_t topOID;
253 get_top (args["d"], topOID);
254
255 if (!get_info (topOID, args["c"], metadata, getParents, collectproto, response, logout))
256 return;
257
258 textout << outconvert << disp << get_formatted_string (response.docInfo[0], formatlistptr);
259}
260
261
262static void recurse_contents (ResultDocInfo_t &section, cgiargsclass &args,
263 browserclass *bptr, text_tset &metadata, bool &getParents,
264 format_t *formatlistptr, format_tmap &formatlistmap,
265 formatinfo_t &formatinfo, browsermapclass *browsermap,
266 int colnumber, recptproto *collectproto, displayclass &disp,
267 outconvertclass &outconvert, ostream &textout, ostream &logout) {
268 text_t formatstring;
269
270 bool is_classify = false;
271 if (args["d"].empty()) is_classify = true;
272
273 // output this section
274 bool use_table = is_table_content (formatlistptr);
275 colnumber += bptr->output_section_group (section, args, colnumber, formatlistptr, use_table,
276 metadata, getParents, collectproto, disp, outconvert,
277 textout, logout);
278
279 text_t classification;
280 if (!is_classify) classification = "Document";
281 else get_top (section.OID, classification);
282
283 int haschildren = section.metadata["haschildren"].values[0].getint();
284 const text_t &doctype = section.metadata["doctype"].values[0];
285 text_t classifytype = section.metadata["classifytype"].values[0];
286 // HLists are displayed as VLists when contents are expanded,
287 // Paged documents are displayed as HLists
288 if (classifytype == "HList") classifytype = "VList";
289 if (classifytype == "Paged") classifytype = "HList";
290
291 // recurse through children
292 if ((haschildren == 1) && ((!is_classify) || (doctype == "classify"))) {
293
294 // get browser for displaying children
295 bptr = browsermap->getbrowser (classifytype);
296 bptr->load_metadata_defaults (metadata);
297
298 // get the formatstring if there is one
299 if (!get_formatstring (classification, classifytype,
300 formatinfo.formatstrings, formatstring))
301 formatstring = bptr->get_default_formatstring();
302
303 format_tmap::const_iterator it = formatlistmap.find (formatstring);
304 // check if formatlistptr is cached
305 if (it != formatlistmap.end()) formatlistptr = (*it).second;
306 else {
307 formatlistptr = new format_t();
308 parse_formatstring (formatstring, formatlistptr, metadata, getParents);
309 formatlistmap[formatstring] = formatlistptr;
310 }
311
312 FilterResponse_t tmp;
313 get_children (section.OID, args["c"], metadata, getParents, collectproto, tmp, logout);
314 ResultDocInfo_tarray::iterator thisdoc = tmp.docInfo.begin();
315 ResultDocInfo_tarray::iterator lastdoc = tmp.docInfo.end();
316
317 while (thisdoc != lastdoc) {
318 recurse_contents (*thisdoc, args, bptr, metadata, getParents,
319 formatlistptr, formatlistmap, formatinfo, browsermap,
320 colnumber, collectproto, disp, outconvert, textout, logout);
321 thisdoc ++;
322 }
323 }
324}
325
326
327// expanded_contents recurses through all contents. there's a special case
328// for an HList when contents are expanded (i.e. it's displayed as a VList)
329//
330// if we're inside a document we expand all contents from the top,
331// if we're at classification level we'll just expand out those contents below
332// the current one
333
334static void expanded_contents (cgiargsclass &args, browsermapclass *browsermap,
335 formatinfo_t &formatinfo, recptproto *collectproto,
336 displayclass &disp, outconvertclass &outconvert,
337 ostream &textout, ostream &logout) {
338
339 if (args["d"].empty() && args["cl"].empty()) return;
340 text_t OID;
341
342 FilterResponse_t response;
343 bool getParents = false;
344 text_tset metadata;
345 text_t classifytype, classification, formatstring;
346 int colnumber = 0;
347
348 if (!args["d"].empty()) {
349 // document level - expand from top
350 get_top (args["d"], OID);
351 classification = "Document";
352 } else {
353 // classification level
354 OID = args["cl"];
355 get_top (args["cl"], classification);
356 }
357
358 // get classifytype of this level
359 text_t tOID;
360 if (is_top(OID)) {
361 classifytype = "thistype";
362 tOID = OID;
363 } else {
364 classifytype = "childtype";
365 tOID = get_parent (OID);
366 }
367 metadata.insert (classifytype);
368
369 if (!get_info (tOID, args["c"], metadata, getParents, collectproto, response, logout))
370 return;
371 classifytype = response.docInfo[0].metadata[classifytype].values[0];
372 // if we still don't have a classifytype we'll use the default
373 if (classifytype.empty()) {
374 browserclass *bptr = browsermap->get_default_browser ();
375 classifytype = bptr->get_browser_name ();
376 }
377
378 // HLists are displayed as VLists when contents are expanded,
379 // Books are displayed as HLists
380 if (classifytype == "HList") classifytype = "VList";
381 if (classifytype == "Book") classifytype = "HList";
382
383 metadata.erase (metadata.begin(), metadata.end());
384
385 // metadata elements needed by recurse_contents
386 metadata.insert ("classifytype");
387 metadata.insert ("doctype");
388 metadata.insert ("haschildren");
389
390 // load up metadata array with browser defaults
391 browserclass *bptr = browsermap->getbrowser (classifytype);
392 bptr->load_metadata_defaults (metadata);
393
394 // get the formatstring if there is one or use the browsers default
395 if (!get_formatstring (classification, classifytype,
396 formatinfo.formatstrings, formatstring))
397 formatstring = bptr->get_default_formatstring();
398
399 format_t *formatlistptr = new format_t();
400 parse_formatstring (formatstring, formatlistptr, metadata, getParents);
401
402 // protocol call
403 if (!get_info (OID, args["c"], metadata, getParents, collectproto, response, logout))
404 return;
405
406 format_tmap formatlistmap;
407 formatlistmap[formatstring] = formatlistptr;
408
409 recurse_contents (response.docInfo[0], args, bptr, metadata,
410 getParents, formatlistptr, formatlistmap, formatinfo, browsermap,
411 colnumber, collectproto, disp, outconvert, textout, logout);
412
413 // clean up format list pointers
414 format_tmap::const_iterator here = formatlistmap.begin();
415 format_tmap::const_iterator end = formatlistmap.end();
416 while (here != end) {
417 delete (*here).second;
418 here ++;
419 }
420}
421
422
423static void load_formatstring (const text_t &classifytype, text_tset &metadata,
424 bool &getParents, const text_t &classification,
425 browsermapclass *browsermap, formatinfo_t &formatinfo,
426 format_tmap &formatlistmap) {
427 text_t formatstring;
428
429 // load up metadata array with browser defaults
430 browserclass *bptr = browsermap->getbrowser (classifytype);
431 bptr->load_metadata_defaults (metadata);
432
433 // get the formatstring if there is one or use the browsers default
434 if (!get_formatstring (classification, classifytype,
435 formatinfo.formatstrings, formatstring))
436 formatstring = bptr->get_default_formatstring();
437
438 // see if it's cached
439 format_tmap::const_iterator it = formatlistmap.find (formatstring);
440 if (it == formatlistmap.end()) {
441 format_t *formatlistptr = new format_t();
442 parse_formatstring (formatstring, formatlistptr, metadata, getParents);
443 formatlistmap[formatstring] = formatlistptr;
444 }
445}
446
447static void load_formatstrings (FilterResponse_t &response, text_tset &metadata,
448 bool &getParents, const text_t &classification,
449 browsermapclass *browsermap, formatinfo_t &formatinfo,
450 format_tmap &formatlistmap) {
451
452 text_tset cache;
453
454 ResultDocInfo_tarray::iterator thisdoc = response.docInfo.begin();
455 ResultDocInfo_tarray::iterator lastdoc = response.docInfo.end();
456
457 while (thisdoc != lastdoc) {
458
459 if (is_top ((*thisdoc).OID))
460 load_formatstring ((*thisdoc).metadata["thistype"].values[0], metadata,
461 getParents, classification, browsermap, formatinfo,
462 formatlistmap);
463
464 text_t &childtype = (*thisdoc).metadata["childtype"].values[0];
465 text_tset::const_iterator it = cache.find (childtype);
466 if (it == cache.end()) {
467 load_formatstring (childtype, metadata, getParents, classification,
468 browsermap, formatinfo, formatlistmap);
469 cache.insert (childtype);
470 }
471 thisdoc ++;
472 }
473}
474
475static void output_parents (FilterResponse_t &response, cgiargsclass &args,
476 browsermapclass *browsermap, formatinfo_t &formatinfo,
477 format_tmap &formatlistmap, const text_t &classification,
478 int &colnumber, text_tset &metadata, bool &getParents,
479 recptproto *collectproto, displayclass &disp,
480 outconvertclass &outconvert, ostream &textout,
481 ostream &logout) {
482
483 format_t *formatlistptr = NULL;
484 text_t classifytype, formatstring;
485 bool use_table, first = true;
486 ResultDocInfo_tarray::iterator thisparent = response.docInfo.begin();
487 ResultDocInfo_tarray::iterator lastparent = response.docInfo.end();
488 while (thisparent != lastparent) {
489
490 // get classifytype of this level
491 if (is_top ((*thisparent).OID)) classifytype = (*thisparent).metadata["thistype"].values[0];
492 else if (!first) classifytype = (*(thisparent-1)).metadata["childtype"].values[0];
493
494 // if we still don't have a classifytype we'll use the default
495 if (classifytype.empty()) {
496 browserclass *bptr = browsermap->get_default_browser ();
497 classifytype = bptr->get_browser_name ();
498 }
499
500 browserclass *bptr = browsermap->getbrowser (classifytype);
501
502 // get the formatstring if there is one or use the browsers default
503 if (!get_formatstring (classification, classifytype,
504 formatinfo.formatstrings, formatstring))
505 formatstring = bptr->get_default_formatstring();
506
507 // see if it's cached
508 format_tmap::const_iterator it = formatlistmap.find (formatstring);
509 if (it != formatlistmap.end()) formatlistptr = (*it).second;
510 else {
511 logout << "browsetools error\n";
512 return;
513 }
514
515 use_table = is_table_content (formatlistptr);
516 colnumber += bptr->output_section_group (*thisparent, args, colnumber, formatlistptr, use_table,
517 metadata, getParents, collectproto, disp, outconvert,
518 textout, logout);
519 first = false;
520 thisparent ++;
521 }
522}
523
524
525static void contracted_contents (cgiargsclass &args, browsermapclass *browsermap,
526 formatinfo_t &formatinfo, recptproto *collectproto,
527 displayclass &disp, outconvertclass &outconvert,
528 ostream &textout, ostream &logout) {
529 FilterResponse_t response;
530 text_tset metadata;
531 bool getParents = false;
532 text_t formatstring;
533 text_tarray parents;
534 text_t OID = args["d"];
535 text_t classification = "Document";
536 if (OID.empty()) {
537 OID = args["cl"];
538 get_top (OID, classification);
539 }
540 int colnumber = 0;
541
542 bool haschildren = has_children (OID, args["c"], collectproto, logout);
543
544 if (haschildren) get_parents_array (OID + ".fc", parents);
545 else get_parents_array (OID, parents);
546
547 if (!parents.empty()) {
548 // get classifytypes of each parent
549 metadata.insert ("thistype");
550 metadata.insert ("childtype");
551
552 if (!get_info (parents, args["c"], metadata, getParents, collectproto, response, logout))
553 return;
554
555 // get formatstrings for all parents
556 format_tmap formatlistmap;
557 load_formatstrings (response, metadata, getParents, classification,
558 browsermap, formatinfo, formatlistmap);
559
560 if (!get_info (parents, args["c"], metadata, getParents, collectproto, response, logout))
561 return;
562
563 // display each parent
564 output_parents (response, args, browsermap, formatinfo, formatlistmap,
565 classification, colnumber, metadata, getParents,
566 collectproto, disp, outconvert, textout, logout);
567
568 metadata.erase (metadata.begin(), metadata.end());
569
570 // clean up cached format list pointers
571 format_tmap::const_iterator here = formatlistmap.begin();
572 format_tmap::const_iterator end = formatlistmap.end();
573 while (here != end) {
574 delete (*here).second;
575 here ++;
576 }
577 }
578
579 // get childrens classifytype
580 text_t classifytype;
581 int numparents = response.docInfo.size();
582 if (!parents.empty())
583 classifytype = response.docInfo[numparents-1].metadata["childtype"].values[0];
584 else {
585 // use the default
586 browserclass *bptr = browsermap->get_default_browser ();
587 classifytype = bptr->get_browser_name ();
588 }
589
590 // load up metadata array with browser defaults
591 browserclass *bptr = browsermap->getbrowser (classifytype);
592 bptr->load_metadata_defaults (metadata);
593
594 // get the formatstring if there is one or use the browsers default
595 if (!get_formatstring (classification, classifytype,
596 formatinfo.formatstrings, formatstring))
597 formatstring = bptr->get_default_formatstring();
598
599 format_t *formatlistptr = new format_t();
600 parse_formatstring (formatstring, formatlistptr, metadata, getParents);
601
602 if (haschildren)
603 get_children (OID, args["c"], metadata, getParents,
604 collectproto, response, logout);
605 else
606 get_children (OID + ".pr", args["c"], metadata, getParents,
607 collectproto, response, logout);
608
609 // display children
610 bool use_table = is_table_content (formatlistptr);
611 bptr->output_section_group (response, args, colnumber, formatlistptr, use_table,
612 metadata, getParents, collectproto, disp, outconvert,
613 textout, logout);
614
615 delete formatlistptr;
616}
617
618void output_toc (cgiargsclass &args, browsermapclass *browsermap,
619 formatinfo_t &formatinfo, recptproto *collectproto,
620 displayclass &disp, outconvertclass &outconvert,
621 ostream &textout, ostream &logout) {
622
623 bool havecontrols = false;
624
625 // get the cover image (if there is one) and the control buttons
626 // if we're inside a book
627 if (!args["d"].empty()) {
628 textout << "<p><table cellpadding=0 cellspacing=0><tr>\n";
629 textout << "<td valign=top width=200>\n";
630 if (formatinfo.DocumentImages)
631 output_cover_image (args, collectproto, disp, outconvert, textout, logout);
632 else if (formatinfo.DocumentTitles)
633 output_titles (args, collectproto, formatinfo, disp, outconvert, textout, logout);
634 output_controls (args, formatinfo.DocumentButtons, collectproto, disp,
635 outconvert, textout, logout);
636 textout << "</td><td valign=top>\n";
637 havecontrols = true;
638 }
639
640 if (formatinfo.DocumentContents) {
641 if (args.getintarg("gc") == 1) {
642
643 // expanded table of contents
644 expanded_contents (args, browsermap, formatinfo, collectproto,
645 disp, outconvert, textout, logout);
646 } else {
647
648 // contracted table of contents
649 contracted_contents (args, browsermap, formatinfo, collectproto,
650 disp, outconvert, textout, logout);
651 }
652 }
653
654 if (havecontrols) textout << "</td></tr></table>\n";
655}
Note: See TracBrowser for help on using the repository browser.