source: trunk/gsdl/src/recpt/documentaction.cpp@ 757

Last change on this file since 757 was 738, checked in by sjboddie, 25 years ago

added FullTOC option

  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 31.3 KB
Line 
1/**********************************************************************
2 *
3 * documentaction.cpp --
4 * Copyright (C) 1999 The New Zealand Digital Library Project
5 *
6 * A component of the Greenstone digital library software
7 * from the New Zealand Digital Library Project at the
8 * University of Waikato, New Zealand.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 *
24 * $Id: documentaction.cpp 738 1999-10-24 07:23:40Z sjboddie $
25 *
26 *********************************************************************/
27
28/*
29 $Log$
30 Revision 1.29 1999/10/24 07:23:40 sjboddie
31 added FullTOC option
32
33 Revision 1.28 1999/10/19 03:23:42 davidb
34 Collection building support through web pages
35 and internal and external link handling for collection documents
36
37 Revision 1.27 1999/10/14 23:00:53 sjboddie
38 finished changes to browsing support
39
40 Revision 1.26 1999/10/10 08:14:06 sjboddie
41 - metadata now returns mp rather than array
42 - redesigned browsing support (although it's not finished so
43 won't currently work ;-)
44
45 Revision 1.25 1999/09/17 04:46:05 sjboddie
46 fixed a couple of problems with 'unknown' classifier
47
48 Revision 1.24 1999/09/17 04:00:26 sjboddie
49 tidied up navigation bar to produce a default "unknown" button if
50 it comes across metadata it can't display
51
52 Revision 1.23 1999/09/07 04:56:54 sjboddie
53 added GPL notice
54
55 Revision 1.22 1999/08/20 01:00:22 sjboddie
56 split some of the larger functions up to simplify the creation of
57 collection specific receptionists
58
59 Revision 1.21 1999/08/11 23:28:03 sjboddie
60 -added support for html classifier
61 - removed _random_ macro - now use _blank for detach page
62
63 Revision 1.20 1999/08/10 23:16:39 sjboddie
64 a couple of small changes to get format options DocumentArrowsBottom
65 and DocumentArrowsTop working correctly
66
67 Revision 1.19 1999/08/10 22:40:01 sjboddie
68 added some more format options including the ability to format the
69 document text
70
71 Revision 1.18 1999/08/09 04:25:18 sjboddie
72 moved OID translation stuff from documentaction::define_external_macros
73 to receptionist
74
75 Revision 1.17 1999/08/09 02:13:53 sjboddie
76 fixed small bug in ShowSectionTitles
77
78 Revision 1.16 1999/08/03 03:30:47 sjboddie
79 a few small changes related to new format options
80
81 Revision 1.15 1999/07/30 02:18:49 sjboddie
82 -added collectinfo argument to some functions
83 -caught up with changes to browsetools (allowing nested classifications)
84 -added showtoppage format option
85
86 Revision 1.14 1999/07/21 05:01:09 sjboddie
87 fixed up wrapping of classificationlinks
88
89 Revision 1.13 1999/07/20 02:59:54 sjboddie
90 List and AZList classifications now use format strings
91
92 Revision 1.12 1999/07/16 00:19:01 sjboddie
93 some changes to the way quoted queries are handled
94
95 Revision 1.11 1999/07/07 05:47:41 sjboddie
96 changed around the way browsetools works
97
98 Revision 1.10 1999/06/29 01:46:44 sjboddie
99 now sets a _navigationbar_ macro even if there aren't any
100 classifications (it will just have the 'search' button
101
102 Revision 1.9 1999/06/27 22:05:58 sjboddie
103 now set a _thisOID_ macro for use in displaying images
104
105 Revision 1.8 1999/06/24 05:12:20 sjboddie
106 lots of small changes
107
108 Revision 1.7 1999/06/17 03:06:58 sjboddie
109 got detach button working properly - the close book icon is now disabled
110 when page is detached as the javascript close() function I was using is
111 too unreliable over different browsers
112 note that in my last comment I meant the "cl" arg (not the "c" arg).
113
114 Revision 1.6 1999/06/16 23:53:15 sjboddie
115 tidied a few things up. documentaction::define_external_macros now
116 resets the "c" arg if it's set to something stupid by the .xx suffixes
117
118 Revision 1.5 1999/06/16 03:10:49 sjboddie
119 define_internal_macros() now sets _pagetitle_ macro to document's title
120 (including parents of current document)
121
122 Revision 1.4 1999/06/15 01:55:29 sjboddie
123 - got text highlighting working
124 - got multiple collections working (now outputs error message if an
125 attempt is made to get a document when the "c" arg isn't set.
126
127 Revision 1.3 1999/06/08 04:29:37 sjboddie
128 added argsinfo to the call to check_cgiargs to make it easy to set
129 args to their default if they're found to be screwed up
130
131 Revision 1.2 1999/05/10 03:40:35 sjboddie
132 lots of changes - slowly getting document action sorted out
133
134 Revision 1.1 1999/04/30 01:59:40 sjboddie
135 lots of stuff - getting documentaction working (documentaction replaces
136 old browseaction)
137
138 Revision 1.2 1999/03/29 02:14:27 sjboddie
139
140 More changes to browseaction
141
142 Revision 1.1 1999/03/25 03:09:40 sjboddie
143
144 subjectbrowseaction became browseaction
145
146
147 */
148
149
150#include <string.h>
151#include "documentaction.h"
152#include "browsetools.h"
153#include "OIDtools.h"
154#include "querytools.h"
155#include "unitool.h"
156
157documentaction::documentaction () {
158
159 // this action uses cgi variables "a", "d", "cl",
160 // "x", "gc", "gt", "gp", and "hl"
161 cgiarginfo arg_ainfo;
162 arg_ainfo.shortname = "a";
163 arg_ainfo.longname = "action";
164 arg_ainfo.multiplechar = true;
165 arg_ainfo.defaultstatus = cgiarginfo::weak;
166 arg_ainfo.argdefault = "p";
167 arg_ainfo.savedarginfo = cgiarginfo::must;
168 argsinfo.addarginfo (NULL, arg_ainfo);
169
170 arg_ainfo.shortname = "d";
171 arg_ainfo.longname = "document OID";
172 arg_ainfo.multiplechar = true;
173 arg_ainfo.defaultstatus = cgiarginfo::none;
174 arg_ainfo.argdefault = "";
175 arg_ainfo.savedarginfo = cgiarginfo::can;
176 argsinfo.addarginfo (NULL, arg_ainfo);
177
178 // whether or not a document should be retrieved from the
179 // library or the Web.
180 arg_ainfo.shortname = "il";
181 arg_ainfo.longname = "internal link preference";
182 arg_ainfo.multiplechar = false;
183 arg_ainfo.defaultstatus = cgiarginfo::weak;
184 arg_ainfo.argdefault = "l";
185 arg_ainfo.savedarginfo = cgiarginfo::must;
186 argsinfo.addarginfo (NULL, arg_ainfo);
187
188 arg_ainfo.shortname = "cl";
189 arg_ainfo.longname = "classification OID";
190 arg_ainfo.multiplechar = true;
191 arg_ainfo.defaultstatus = cgiarginfo::none;
192 arg_ainfo.argdefault = "";
193 arg_ainfo.savedarginfo = cgiarginfo::can;
194 argsinfo.addarginfo (NULL, arg_ainfo);
195
196 // in this action "gc" controls the expand/contract
197 // contents function
198 arg_ainfo.shortname = "gc";
199 arg_ainfo.longname = "expand contents";
200 arg_ainfo.multiplechar = false;
201 arg_ainfo.defaultstatus = cgiarginfo::weak;
202 arg_ainfo.argdefault = "0";
203 arg_ainfo.savedarginfo = cgiarginfo::can;
204 argsinfo.addarginfo (NULL, arg_ainfo);
205
206 // in this action "gt" controls the expand/contract
207 // text function 0 = not expanded, 1 = expand unless
208 // there are more than 10 sections containing text,
209 // 2 = expand all
210 arg_ainfo.shortname = "gt";
211 arg_ainfo.longname = "expand text";
212 arg_ainfo.multiplechar = false;
213 arg_ainfo.defaultstatus = cgiarginfo::weak;
214 arg_ainfo.argdefault = "0";
215 arg_ainfo.savedarginfo = cgiarginfo::can;
216 argsinfo.addarginfo (NULL, arg_ainfo);
217
218 // in this action "gp" is the "go to page" control
219 // used by the Book type of toc
220 arg_ainfo.shortname = "gp";
221 arg_ainfo.longname = "go to page";
222 arg_ainfo.multiplechar = true;
223 arg_ainfo.defaultstatus = cgiarginfo::none;
224 arg_ainfo.argdefault = "";
225 arg_ainfo.savedarginfo = cgiarginfo::mustnot;
226 argsinfo.addarginfo (NULL, arg_ainfo);
227
228 // in this action "hl" is the "highlighting on/
229 // highlighting off control
230 arg_ainfo.shortname = "hl";
231 arg_ainfo.longname = "highlighting on/off";
232 arg_ainfo.multiplechar = false;
233 arg_ainfo.defaultstatus = cgiarginfo::weak;
234 arg_ainfo.argdefault = "1";
235 arg_ainfo.savedarginfo = cgiarginfo::must;
236 argsinfo.addarginfo (NULL, arg_ainfo);
237
238 // "x" is 0 normally or 1 if page
239 // has been "detached"
240 arg_ainfo.shortname = "x";
241 arg_ainfo.longname = "detached page";
242 arg_ainfo.multiplechar = false;
243 arg_ainfo.defaultstatus = cgiarginfo::weak;
244 arg_ainfo.argdefault = "0";
245 arg_ainfo.savedarginfo = cgiarginfo::must;
246 argsinfo.addarginfo (NULL, arg_ainfo);
247}
248
249documentaction::~documentaction () {
250}
251
252bool documentaction::check_cgiargs (cgiargsinfoclass &argsinfo, cgiargsclass &args,
253 ostream &logout) {
254
255 // check gc argument
256 int arg_gc = args.getintarg("gc");
257 if (arg_gc != 0 && arg_gc != 1) {
258 logout << "Warning: \"gc\" argument out of range (" << arg_gc << ")\n";
259 cgiarginfo *gcinfo = argsinfo.getarginfo ("gc");
260 if (gcinfo != NULL) args["gc"] = gcinfo->argdefault;
261 }
262
263 // check gt argument (may be either 0, 1 or 2)
264 int arg_gt = args.getintarg("gt");
265 if (arg_gt != 0 && arg_gt != 1 && arg_gt != 2) {
266 logout << "Warning: \"gt\" argument out of range (" << arg_gt << ")\n";
267 cgiarginfo *gtinfo = argsinfo.getarginfo ("gt");
268 if (gtinfo != NULL) args["gt"] = gtinfo->argdefault;
269 }
270
271 // check hl argument
272 int arg_hl = args.getintarg("hl");
273 if (arg_hl != 0 && arg_hl != 1) {
274 logout << "Warning: \"hl\" argument out of range (" << arg_hl << ")\n";
275 cgiarginfo *hlinfo = argsinfo.getarginfo ("hl");
276 if (hlinfo != NULL) args["hl"] = hlinfo->argdefault;
277 }
278
279 // check x argument
280 int arg_x = args.getintarg("x");
281 if (arg_x != 0 && arg_x != 1) {
282 logout << "Warning: \"x\" argument out of range (" << arg_x << ")\n";
283 cgiarginfo *xinfo = argsinfo.getarginfo ("x");
284 if (xinfo != NULL) args["x"] = xinfo->argdefault;
285 }
286
287 return true;
288}
289
290void documentaction::get_cgihead_info (cgiargsclass &args, response_t &response,
291 text_t &response_data, ostream &logout) {
292
293 if ((!args["d"].empty()) && (args["il"] == "w"))
294 {
295 text_t &oid = args["d"];
296 text_t &collection = args["c"];
297
298 recptprotolistclass* protocols = recpt->get_recptprotolist_ptr();
299 recptproto* collectproto = protocols->getrecptproto (collection, logout);
300
301 text_tset metadata;
302 FilterResponse_t filt_response;
303
304 metadata.insert ("URL");
305
306 // get metadata for this document and it's parents
307 if (get_info (oid, collection, metadata, true, collectproto, filt_response, logout))
308 {
309 text_t url = *(filt_response.docInfo[0].metadata[0].values.begin());
310
311 response = location;
312 response_data = url;
313 }
314 else
315 {
316 // error, no URL
317 logout << "Error: documentaction::get_cgihead_info failed on get_info" << endl;
318 }
319 }
320 else
321 {
322 response = content;
323 response_data = "text/html";
324 }
325}
326
327// set_widthtspace calculates how wide the spaces in the nav bar should
328// be and sets the appropriate macro
329void documentaction::set_spacemacro (displayclass &disp, FilterResponse_t &response) {
330
331 text_t width;
332 int twidth, swidth, iwidth = 0;
333
334 int numc = response.docInfo.size();
335 ResultDocInfo_tarray::iterator dochere = response.docInfo.begin();
336 ResultDocInfo_tarray::iterator docend = response.docInfo.end();
337
338 disp.expandstring ("Global", "_pagewidth_", width);
339 twidth = width.getint();
340
341 disp.expandstring ("query", "_searchwidth_", width);
342 iwidth += width.getint();
343
344 while (dochere != docend) {
345 const text_t &title = (*dochere).metadata["Title"].values[0];
346
347 disp.expandstring ("document", "_" + title + "width_", width);
348 if (width == ("_" + title + "width_"))
349 disp.expandstring ("document", "_defaultwidth_", width);
350 iwidth += width.getint();
351 dochere ++;
352 }
353 if ((twidth - iwidth) < numc) swidth = 2;
354 else {
355 swidth = twidth - iwidth;
356 if (numc > 0) swidth = swidth / numc;
357 }
358 disp.setmacro ("widthtspace", "Global", swidth);
359}
360
361// set_navbarmacros sets _navigationbar_, _javaimagesnavbar_ and _httpbrowseXXX_ macros
362// reponse contains 1 metadata field (Title)
363void documentaction::set_navbarmacros (displayclass &disp, FilterResponse_t &response,
364 cgiargsclass &args) {
365
366 text_t javaimagesnavbar, topparent;
367 text_t &arg_d = args["d"];
368 text_t navigationbar = "<!-- Navigation Bar -->\n";
369
370 get_top (args["cl"], topparent);
371 int numc = response.docInfo.size();
372 ResultDocInfo_tarray::iterator dochere = response.docInfo.begin();
373 ResultDocInfo_tarray::iterator docend = response.docInfo.end();
374
375 navigationbar += "<nobr>\n";
376 if (args["a"] == "q") {
377 navigationbar += "_icontabsearchgreen_";
378 } else {
379 navigationbar += "_imagesearch_";
380 javaimagesnavbar = "_javasearch_";
381 }
382 if (numc == 0) navigationbar += "_imagespacer_";
383
384 while (dochere != docend) {
385 text_t title = (*dochere).metadata["Title"].values[0];
386
387 bool unknown = false;
388
389 // test the _XXXwidth_ macro to see if image macros are
390 // defined for this type of classification - if not we'll
391 // just display the text
392 text_t tmpwidth;
393 disp.expandstring ("document", "_" + title + "width_", tmpwidth);
394 if (tmpwidth == ("_" + title + "width_")) unknown = true;
395
396 // if we're inside a document all the classification buttons should be enabled
397 if (arg_d.empty() && ((*dochere).OID == topparent)) {
398 if (unknown) navigationbar += "_imagespacer_&nbsp;" + title + "&nbsp;";
399 else navigationbar += "_imagespacer__icontab" + title + "green_";
400 } else {
401
402 // set the _httpbrowseXXX_ macro for this classification
403 if (unknown) navigationbar += "_imagespacer_&nbsp;<a href=\"_httpdocument_&cl=" +
404 (*dochere).OID + "\">" + title + "</a>&nbsp;";
405 else {
406 navigationbar += "_imagespacer__image" + title + "_";
407 disp.setmacro ("httpbrowse" + title, "Global", "_httpdocument_&cl=" + (*dochere).OID);
408 }
409 }
410 if (!unknown) javaimagesnavbar += "_java" + title + "_";
411 dochere ++;
412 }
413 navigationbar += "\n</nobr>\n";
414 navigationbar += "<!-- End of Navigation Bar -->\n";
415 disp.setmacro ("navigationbar", "Global", navigationbar);
416 if (args.getintarg("v") == 0)
417 disp.setmacro ("javaimagesnavbar", "Global", javaimagesnavbar);
418}
419
420// define all the macros which might be used by other actions
421// to produce pages.
422void documentaction::define_external_macros (const ColInfoResponse_t &/*collectinfo*/,
423 displayclass &disp, cgiargsclass &args,
424 recptproto *collectproto, ostream &logout) {
425
426 // define_external_macros sets the following macros:
427
428 // _navigationbar_ this is the navigation bar containing the search button
429 // and any classification buttons - it goes at the top of
430 // most pages. for now we're assuming that there'll always
431 // be a search button - we should probably check that there
432 // is a query action before making this assumption
433
434 // _httpbrowseXXX_ the http macros for each classification (i.e. if there
435 // are Title and Creator classifications _httpbrowseTitle_
436 // and _httpbrowseCreator_ will be set
437
438 // _javaimagesnavbar_ this is the javascript code to shove in to make the
439 // flashy images used by _navigationbar_ work
440
441 // _widthtspace_ the width of the spacers between buttons in navigation
442 // bar
443
444
445 // can't do anything if collectproto is null (i.e. no collection was specified)
446 if (collectproto == NULL) return;
447
448 outconvertclass text_t2ascii;
449 comerror_t err;
450 InfoFiltersResponse_t filterinfo;
451 FilterResponse_t response;
452 text_tset metadata;
453 text_t &collection = args["c"];
454
455 // don't want navigation bar if page is 'detached'
456 if (!args.getintarg("x")) {
457
458 collectproto->get_filterinfo (collection, filterinfo, err, logout);
459 if (err == noError) {
460 // check that there's a browse filter
461 if (filterinfo.filterNames.find ("BrowseFilter") != filterinfo.filterNames.end()) {
462
463 metadata.insert ("Title");
464 bool getParents = false;
465 get_children ("", collection, metadata, getParents, collectproto, response, logout);
466
467 // calculate width of spacers and set _widthtspace_ macro
468 if (args.getintarg("v") == 0) set_spacemacro (disp, response);
469
470 // set _navigationbar_ and _javaimagesnavbar_ macros
471 set_navbarmacros (disp, response, args);
472 }
473 } else {
474 logout << text_t2ascii
475 << "Error (documentaction::define_external_macros()) in call to get_filterinfo() "
476 << get_comerror_string (err);
477 }
478 }
479}
480
481void documentaction::load_formatinfo (const text_tmap &colformat, int gt) {
482
483 formatinfo.clear();
484 text_tmap::const_iterator format_here = colformat.begin();
485 text_tmap::const_iterator format_end = colformat.end();
486
487 while (format_here != format_end) {
488 if (((*format_here).first == "DocumentImages") &&
489 ((*format_here).second == "true"))
490 formatinfo.DocumentImages = true;
491 else if (((*format_here).first == "DocumentTitles") &&
492 ((*format_here).second == "false"))
493 formatinfo.DocumentTitles = false;
494 else if ((*format_here).first == "DocumentHeading")
495 formatinfo.DocumentHeading = (*format_here).second;
496 else if (((*format_here).first == "DocumentContents") &&
497 ((*format_here).second == "false"))
498 formatinfo.DocumentContents = false;
499 else if (((*format_here).first == "DocumentArrowsBottom") &&
500 ((*format_here).second == "false"))
501 formatinfo.DocumentArrowsBottom = false;
502 else if ((*format_here).first == "DocumentButtons")
503 splitchar ((*format_here).second.begin(), (*format_here).second.end(),
504 '|', formatinfo.DocumentButtons);
505 else if ((*format_here).first == "DocumentText")
506 formatinfo.DocumentText = (*format_here).second;
507 else
508 formatinfo.formatstrings[(*format_here).first] = (*format_here).second;
509
510 format_here ++;
511 }
512
513 // never want arrows when text is expanded
514 if (gt)
515 formatinfo.DocumentArrowsBottom = false;
516}
517
518void documentaction::set_java_macros (cgiargsclass &args, displayclass &disp) {
519
520 text_t javaimagescontent = "_javaextras_";
521
522 int arg_gt = args.getintarg("gt");
523 int arg_gc = args.getintarg("gc");
524 int arg_hl = args.getintarg("hl");
525
526 text_tarray::const_iterator button_here = formatinfo.DocumentButtons.begin();
527 text_tarray::const_iterator button_end = formatinfo.DocumentButtons.end();
528
529 while (button_here != button_end) {
530 if (*button_here == "Detach")
531 javaimagescontent += "_javadetach_";
532 else if (*button_here == "Expand Text") {
533 if (arg_gt == 1)
534 javaimagescontent += "_javacontracttext__javacontinue_";
535 else if (arg_gt == 2)
536 javaimagescontent += "_javacontracttext_";
537 else
538 javaimagescontent += "_javaexpandtext_";
539 } else if (*button_here == "Expand Contents") {
540 if (arg_gc == 1)
541 javaimagescontent += "_javacontractcontents_";
542 else
543 javaimagescontent += "_javaexpandcontents_";
544 } else if (*button_here == "Highlight") {
545 if (arg_hl == 1)
546 javaimagescontent += "_javanohighlighting_";
547 else
548 javaimagescontent += "_javahighlighting_";
549 }
550 button_here ++;
551 }
552 disp.setmacro ("javaimagescontent", "document", javaimagescontent);
553}
554
555
556// define all the macros which are related to pages generated
557// by this action. we also load up the formatinfo structure
558// here (it's used in do_action as well as here)
559void documentaction::define_internal_macros (const ColInfoResponse_t &collectinfo,
560 displayclass &disp, cgiargsclass &args,
561 recptproto *collectproto, ostream &logout) {
562
563 // define_internal_macros sets the following macros:
564
565 // _pagetitle_ the title to be displayed at the top of the browser window
566
567 // _imagethispage_ the title image to be displayed at top right of page
568
569 // _navarrows_ this may be overridden to "" when format option
570 // DocumentArrowsBottom is false
571
572 // _header_ the header macro is overridden if we're not at a top level
573 // classification to remove the title block
574
575 // _javaimagescontent_ this is the javascript code to shove in to make the
576 // flashy buttons work
577
578 // _thisOID_ the OID (directory) of the current document - this corresponds
579 // to the archivedir metadata element
580
581 // can't do anything if collectproto is null (i.e. no collection was specified)
582 if (collectproto == NULL) return;
583
584 text_tset metadata;
585 FilterResponse_t response;
586 text_t &arg_d = args["d"];
587 text_t &arg_cl = args["cl"];
588 text_t &collection = args["c"];
589 int gt = args.getintarg("gt");
590 load_formatinfo (collectinfo.format, gt);
591
592 if (!formatinfo.DocumentArrowsBottom)
593 disp.setmacro("navarrows", "document", "");
594
595 metadata.insert ("Title");
596
597 bool fulltoc = false;
598
599 if (args["cl"] != "search") {
600 // see if there's a FullTOC string
601 text_t cl_top, full_toc;
602 get_top (arg_cl, cl_top);
603 if (get_formatstring (cl_top, "FullTOC", formatinfo.formatstrings, full_toc))
604 if (full_toc == "true") fulltoc = true;
605 }
606
607 if (!arg_d.empty() && !fulltoc) {
608 // we're at document level
609
610 metadata.insert ("archivedir");
611
612 // get metadata for this document and it's parents
613 if (get_info (arg_d, collection, metadata, true, collectproto, response, logout)) {
614 disp.setmacro ("header", "document", "_textheader_");
615
616 text_tarray pagetitlearray;
617 if (!response.docInfo[0].metadata["Title"].values[0].empty())
618 pagetitlearray.push_back (response.docInfo[0].metadata["Title"].values[0]);
619 if (!gt) {
620 MetadataInfo_t *parenttitle = response.docInfo[0].metadata["Title"].parent;
621 while (parenttitle != NULL) {
622 if (!parenttitle->values[0].empty())
623 pagetitlearray.push_back (parenttitle->values[0]);
624 parenttitle = parenttitle->parent;
625 }
626 }
627 reverse (pagetitlearray.begin(), pagetitlearray.end());
628 text_t pagetitle;
629 joinchar (pagetitlearray, ": ", pagetitle);
630 disp.setmacro ("pagetitle", "document", pagetitle);
631
632 if (is_top (arg_d))
633 disp.setmacro ("thisOID", "Global", response.docInfo[0].metadata["archivedir"].values[0]);
634 else {
635 MetadataInfo_t *parentad = response.docInfo[0].metadata["archivedir"].parent;
636 text_t thisOID;
637 while (parentad != NULL) {
638 thisOID = parentad->values[0];
639 parentad = parentad->parent;
640 }
641 disp.setmacro ("thisOID", "Global", thisOID);
642 }
643
644 if (args["u"] != "1")
645 set_java_macros (args, disp);
646
647 }
648 } else {
649 if (!arg_cl.empty()) {
650
651 // get metadata for top level classification
652 text_t classtop;
653 get_top (arg_cl, classtop);
654 if (get_info (classtop, collection, metadata, false, collectproto, response, logout)) {
655
656 text_t &title = response.docInfo[0].metadata["Title"].values[0];
657 bool unknown = false;
658
659 // test the _XXXwidth_ macro to see if image macros are
660 // defined for this type of classification - if not we'll
661 // just display the text
662 text_t tmp;
663 disp.expandstring ("document", "_" + title + "width_", tmp);
664 if (tmp == ("_" + title + "width_")) unknown = true;
665
666 if (unknown) {
667 disp.setmacro ("pagetitle", "document", title);
668 disp.setmacro ("imagethispage", "document", "<h2>" + title + "</h2>");
669 } else {
670 disp.setmacro ("pagetitle", "document", "_text" + title + "page_");
671 disp.setmacro ("imagethispage", "document", "_icon" + title + "page_");
672 }
673 }
674 }
675 }
676}
677
678
679bool documentaction::do_action (cgiargsclass &args, const ColInfoResponse_t &/*collectinfo*/,
680 recptproto *collectproto, displayclass &disp,
681 outconvertclass &outconvert, ostream &textout,
682 ostream &logout) {
683
684 if (collectproto == NULL) {
685 logout << "documentaction::do_action called with NULL collectproto\n";
686 textout << outconvert << disp << "_document:header_\n"
687 << "Error: Attempt to get document without setting collection\n"
688 << "_document:footer_\n";
689 } else {
690
691 text_t OID = args["d"];
692 if (OID.empty()) OID = args["cl"];
693 if (OID.empty()) {
694 textout << outconvert << disp << "Document contains no data_document:footer_\n";
695 return true;
696 }
697
698 textout << outconvert << disp << "_document:header_\n"
699 << "_document:content_\n";
700
701 // output the table of contents
702 output_toc (args, recpt->get_browsermap_ptr(), formatinfo,
703 collectproto, disp, outconvert, textout, logout);
704
705 // output the document text
706 textout << "<p>\n";
707 output_document (OID, args, collectproto, disp, outconvert, textout, logout);
708
709 textout << outconvert << disp << "_document:footer_\n";
710 }
711 return true;
712}
713
714void documentaction::output_text (ResultDocInfo_t &docinfo, format_t *formatlistptr,
715 const TermInfo_tarray &terminfo, const text_t &OID,
716 bool highlight, int hastxt, int wanttext,
717 text_t &collection, recptproto *collectproto,
718 displayclass &disp, outconvertclass &outconvert,
719 ostream &textout, ostream &logout) {
720
721 DocumentRequest_t docrequest;
722 DocumentResponse_t docresponse;
723 comerror_t err;
724
725 if (hastxt == 1) {
726
727 if (wanttext) {
728 // get the text
729 docrequest.OID = OID;
730 collectproto->get_document (collection, docrequest, docresponse, err, logout);
731
732 // cut down on overhead by not using formattools if we only want the text
733 // (wanttext will equal 2 if we want text and other stuff too)
734 if (wanttext == 1)
735 if (highlight)
736 highlighttext(docresponse.doc, terminfo, disp, outconvert, textout, logout);
737 else
738 textout << outconvert << disp << docresponse.doc;
739 }
740
741 if (wanttext != 1) {
742 text_t doctext = get_formatted_string (docinfo, formatlistptr, docresponse.doc);
743
744 if (highlight)
745 highlighttext(doctext, terminfo, disp, outconvert, textout, logout);
746 else
747 textout << outconvert << disp << doctext;
748 }
749 }
750}
751
752
753void documentaction::output_document (const text_t &OID, cgiargsclass &args,
754 recptproto *collectproto, displayclass &disp,
755 outconvertclass &outconvert, ostream &textout,
756 ostream &logout) {
757 FilterResponse_t inforesponse;
758 FilterResponse_t queryresponse;
759 text_tset metadata;
760 bool getParents = false;
761 bool highlight = false;
762 int wanttext = 0;
763 int arg_gt = args.getintarg("gt");
764 text_t &collection = args["c"];
765
766 // if we have a query string and highlighting is turned on we need
767 // to redo the query to get the terms for highlighting
768 if (!args["q"].empty() && args.getintarg("hl")) {
769 FilterRequest_t request;
770 request.filterResultOptions = FRmatchTerms;
771 if (do_query (request, args, collectproto, queryresponse, logout))
772 highlight = true;
773 }
774
775 format_t *formatlistptr = new format_t();
776 parse_formatstring (formatinfo.DocumentText, formatlistptr, metadata, getParents);
777
778 metadata.insert ("hastxt");
779 metadata.insert ("haschildren");
780
781 if (formatinfo.DocumentText == "[Text]")
782 wanttext = 1;
783 else {
784 char *docformat = formatinfo.DocumentText.getcstr();
785 if (strstr (docformat, "[Text]") != NULL)
786 wanttext = 2;
787 delete docformat;
788 }
789
790 if (get_info (OID, collection, metadata, getParents, collectproto, inforesponse, logout)) {
791 int hastxt = inforesponse.docInfo[0].metadata["hastxt"].values[0].getint();
792 int haschildren = inforesponse.docInfo[0].metadata["haschildren"].values[0].getint();
793
794 if (arg_gt == 0) {
795 output_text (inforesponse.docInfo[0], formatlistptr, queryresponse.termInfo,
796 OID, highlight, hastxt, wanttext, collection, collectproto,
797 disp, outconvert, textout, logout);
798
799
800 } else {
801
802 ResultDocInfo_t thisdocinfo = inforesponse.docInfo[0];
803
804 // text is to be expanded
805 text_t exOID = OID;
806 if (haschildren != 1) exOID = get_parent (OID);
807 if (exOID.empty()) exOID = OID;
808
809 // if we're not in a document (i.e. we're in a top level classification)
810 // we need to pass "is_classify = true" to get_contents so that it
811 // doesn't recurse all the way through each document in the classification
812 bool is_classify = false;
813 if (args["d"].empty()) is_classify = true;
814
815 get_contents (exOID, is_classify, metadata, collection,
816 collectproto, inforesponse, logout);
817
818 ResultDocInfo_tarray::iterator sechere = inforesponse.docInfo.begin();
819 ResultDocInfo_tarray::iterator secend = inforesponse.docInfo.end();
820
821 if (arg_gt == 1) {
822 // check if there are more than 10 sections containing text to be expanded -
823 // if there are output warning message - this isn't a great way to do this
824 // since the sections may be very large or very small - one day I'll fix it
825 // -- Stefan.
826 int seccount = 0;
827 while (sechere != secend) {
828 int shastxt = (*sechere).metadata["hastxt"].values[0].getint();
829 if (shastxt == 1) seccount ++;
830 if (seccount > 10) break;
831 sechere ++;
832 }
833 if (seccount > 10) {
834 // more than 10 sections so output warning message and text
835 // for current section only
836 textout << outconvert << disp << "_document:textltwarning_";
837
838 output_text (thisdocinfo, formatlistptr, queryresponse.termInfo,
839 OID, highlight, hastxt, wanttext, collection,
840 collectproto, disp, outconvert, textout, logout);
841
842 }
843 else arg_gt = 2;
844 }
845
846 if (arg_gt == 2) {
847 // get the text for each section
848 sechere = inforesponse.docInfo.begin();
849 int count = 0;
850 while (sechere != secend) {
851 textout << outconvert << disp << "\n<p><a name=" << count << "></a>\n";
852
853 int shastxt = (*sechere).metadata["hastxt"].values[0].getint();
854
855 output_text (*sechere, formatlistptr, queryresponse.termInfo,
856 (*sechere).OID, highlight, shastxt, wanttext, collection,
857 collectproto, disp, outconvert, textout, logout);
858 count ++;
859 sechere ++;
860 }
861 }
862 }
863 }
864 delete formatlistptr;
865}
866
867// highlighttext highlights query terms in text string and outputs the resulting text string
868void documentaction::highlighttext(text_t &text, const TermInfo_tarray &terms,
869 displayclass &disp, outconvertclass &outconvert,
870 ostream &textout, ostream &/*logout*/) {
871
872 text_tmap allterms;
873 text_tmap::const_iterator it;
874
875 // first load all the term variations into a map
876 TermInfo_tarray::const_iterator this_term = terms.begin();
877 TermInfo_tarray::const_iterator last_term = terms.end();
878 while (this_term != last_term) {
879 text_tarray::const_iterator this_var = (*this_term).matchTerms.begin();
880 text_tarray::const_iterator last_var = (*this_term).matchTerms.end();
881 while (this_var != last_var) {
882 allterms[*this_var] = 1;
883 this_var ++;
884 }
885 this_term ++;
886 }
887
888 // get the text to start and end a hightlight
889 text_t starthighlight = "<b><u>";
890 text_t endhighlight = "</u></b>";
891 if (disp.isdefaultmacro("Global", "starthighlight"))
892 disp.expandstring("Global", "_starthighlight_", starthighlight);
893 if (disp.isdefaultmacro("Global", "endhighlight"))
894 disp.expandstring("Global", "_endhighlight_", endhighlight);
895
896
897 text_t::iterator here = text.begin();
898 text_t::iterator end = text.end();
899 text_t word, buffer;
900 while (here != end) {
901 if (is_unicode_letdig(*here)) {
902 // not word boundary
903 word.push_back(*here);
904 here++;
905
906 } else {
907 // found word boundary
908 // add last word if there was one
909 if (!word.empty()) {
910 it = allterms.find(word);
911 if (it != allterms.end()) {
912 word = starthighlight + word + endhighlight;
913 }
914 buffer += word;
915 word.clear();
916 }
917
918 if (*here == '<') {
919 // skip over rest of html tag
920 while ((here != end) && (*here != '>')) {
921 buffer.push_back(*here);
922 here++;
923 }
924 }
925
926 buffer.push_back(*here);
927 here++;
928
929 if (buffer.size() > 1024) {
930 textout << outconvert << disp << buffer;
931 buffer.clear();
932 }
933 }
934 }
935 textout << outconvert << disp << buffer;
936}
Note: See TracBrowser for help on using the repository browser.