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

Last change on this file since 668 was 667, checked in by sjboddie, 25 years ago

finished up on changes to browseing support - may still need some
tidying up

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