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

Last change on this file since 12174 was 12174, checked in by kjdon, 18 years ago

changed the way navigation bar is made. no longer test on tabtextXXX. Just output the same thing whatever case. The macro files will work out what to output

  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 45.2 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 *********************************************************************/
25
26#include <string.h>
27
28#include "documentaction.h"
29#include "OIDtools.h"
30#include "querytools.h"
31#include "unitool.h"
32#include "gsdltools.h"
33#include "highlighttext.h"
34#include "browsetoolsclass.h"
35
36documentaction::documentaction () {
37 recpt = NULL;
38
39 // this action uses cgi variables "a", "d", "cl",
40 // "x", "gc", "gt", "gp", and "hl"
41 cgiarginfo arg_ainfo;
42 arg_ainfo.shortname = "a";
43 arg_ainfo.longname = "action";
44 arg_ainfo.multiplechar = true;
45 arg_ainfo.defaultstatus = cgiarginfo::weak;
46 arg_ainfo.argdefault = "p";
47 arg_ainfo.savedarginfo = cgiarginfo::must;
48 argsinfo.addarginfo (NULL, arg_ainfo);
49
50 arg_ainfo.shortname = "d";
51 arg_ainfo.longname = "document OID";
52 arg_ainfo.multiplechar = true;
53 arg_ainfo.defaultstatus = cgiarginfo::none;
54 arg_ainfo.argdefault = g_EmptyText;
55 arg_ainfo.savedarginfo = cgiarginfo::can;
56 argsinfo.addarginfo (NULL, arg_ainfo);
57
58 // whether or not a document should be retrieved from the
59 // library or the Web.
60 arg_ainfo.shortname = "il";
61 arg_ainfo.longname = "internal link preference";
62 arg_ainfo.multiplechar = false;
63 arg_ainfo.defaultstatus = cgiarginfo::weak;
64 arg_ainfo.argdefault = "l";
65 arg_ainfo.savedarginfo = cgiarginfo::must;
66 argsinfo.addarginfo (NULL, arg_ainfo);
67
68 arg_ainfo.shortname = "cl";
69 arg_ainfo.longname = "classification OID";
70 arg_ainfo.multiplechar = true;
71 arg_ainfo.defaultstatus = cgiarginfo::none;
72 arg_ainfo.argdefault = g_EmptyText;
73 arg_ainfo.savedarginfo = cgiarginfo::can;
74 argsinfo.addarginfo (NULL, arg_ainfo);
75
76 // in this action "gc" controls the expand/contract
77 // contents function
78 arg_ainfo.shortname = "gc";
79 arg_ainfo.longname = "expand contents";
80 arg_ainfo.multiplechar = false;
81 arg_ainfo.defaultstatus = cgiarginfo::weak;
82 arg_ainfo.argdefault = "0";
83 arg_ainfo.savedarginfo = cgiarginfo::can;
84 argsinfo.addarginfo (NULL, arg_ainfo);
85
86 // in this action "gt" controls the expand/contract
87 // text function 0 = not expanded, 1 = expand unless
88 // there are more than 10 sections containing text,
89 // 2 = expand all
90 arg_ainfo.shortname = "gt";
91 arg_ainfo.longname = "expand text";
92 arg_ainfo.multiplechar = false;
93 arg_ainfo.defaultstatus = cgiarginfo::weak;
94 arg_ainfo.argdefault = "0";
95 arg_ainfo.savedarginfo = cgiarginfo::can;
96 argsinfo.addarginfo (NULL, arg_ainfo);
97
98 // in this action "gp" is the "go to page" control
99 // used by the Book type of toc
100 arg_ainfo.shortname = "gp";
101 arg_ainfo.longname = "go to page";
102 arg_ainfo.multiplechar = true;
103 arg_ainfo.defaultstatus = cgiarginfo::none;
104 arg_ainfo.argdefault = g_EmptyText;
105 arg_ainfo.savedarginfo = cgiarginfo::mustnot;
106 argsinfo.addarginfo (NULL, arg_ainfo);
107
108 // in this action "hl" is the "highlighting on/
109 // highlighting off control ("hl" == "2" is a
110 // special case that forces phrase highlighting
111 // to be used even if the query string doesn't
112 // appear to be a phrase)
113 arg_ainfo.shortname = "hl";
114 arg_ainfo.longname = "highlighting on/off";
115 arg_ainfo.multiplechar = false;
116 arg_ainfo.defaultstatus = cgiarginfo::weak;
117 arg_ainfo.argdefault = "1";
118 arg_ainfo.savedarginfo = cgiarginfo::must;
119 argsinfo.addarginfo (NULL, arg_ainfo);
120
121 // "x" is 0 normally or 1 if page
122 // has been "detached"
123 arg_ainfo.shortname = "x";
124 arg_ainfo.longname = "detached page";
125 arg_ainfo.multiplechar = false;
126 arg_ainfo.defaultstatus = cgiarginfo::weak;
127 arg_ainfo.argdefault = "0";
128 arg_ainfo.savedarginfo = cgiarginfo::must;
129 argsinfo.addarginfo (NULL, arg_ainfo);
130
131 // "xx" is 0 normally or 1 if documents should be detached by default
132 arg_ainfo.shortname = "xx";
133 arg_ainfo.longname = "detach all doc pages";
134 arg_ainfo.multiplechar = false;
135 arg_ainfo.defaultstatus = cgiarginfo::weak;
136 arg_ainfo.argdefault = "0";
137 arg_ainfo.savedarginfo = cgiarginfo::must;
138 argsinfo.addarginfo (NULL, arg_ainfo);
139
140
141 // f arg is set to 1 if document is to
142 // be displayed in a frame
143 arg_ainfo.shortname = "f";
144 arg_ainfo.longname = "frame";
145 arg_ainfo.multiplechar = false;
146 arg_ainfo.defaultstatus = cgiarginfo::weak;
147 arg_ainfo.argdefault = "0";
148 arg_ainfo.savedarginfo = cgiarginfo::mustnot;
149 argsinfo.addarginfo (NULL, arg_ainfo);
150
151 // fc arg is "1" if search bar is to be included (i.e. if "fc" == 1
152 // the httpdocument macro will include "&f=1"
153 arg_ainfo.shortname = "fc";
154 arg_ainfo.longname = "include search bar";
155 arg_ainfo.multiplechar = false;
156 arg_ainfo.defaultstatus = cgiarginfo::weak;
157 arg_ainfo.argdefault = "1";
158 arg_ainfo.savedarginfo = cgiarginfo::must;
159 argsinfo.addarginfo (NULL, arg_ainfo);
160
161 //rd is whether a document will be displayed
162 //with a relevant document list
163 arg_ainfo.shortname = "rd";
164 arg_ainfo.longname = "include relevant documents";
165 arg_ainfo.multiplechar = false;
166 arg_ainfo.defaultstatus = cgiarginfo::weak;
167 arg_ainfo.argdefault = "0";
168 arg_ainfo.savedarginfo = cgiarginfo::must;
169 argsinfo.addarginfo (NULL, arg_ainfo);
170
171 //dm is the metadata that has been used for the datelist
172 arg_ainfo.shortname = "dm";
173 arg_ainfo.longname = "date metadata";
174 arg_ainfo.multiplechar = true;
175 arg_ainfo.defaultstatus = cgiarginfo::weak;
176 arg_ainfo.argdefault = g_EmptyText;
177 arg_ainfo.savedarginfo = cgiarginfo::must;
178 argsinfo.addarginfo (NULL, arg_ainfo);
179
180}
181
182documentaction::~documentaction()
183{
184}
185
186bool documentaction::check_cgiargs (cgiargsinfoclass &argsinfo, cgiargsclass &args,
187 recptprotolistclass *protos, ostream &logout) {
188
189 if(!args["d"].empty())
190 {
191 text_t docTop;
192 get_top(args["d"],docTop);
193
194 recptproto* collectproto = protos->getrecptproto (args["c"], logout);
195 if (collectproto != NULL)
196 {
197 ColInfoResponse_t *cinfo = recpt->get_collectinfo_ptr (collectproto, args["c"], logout);
198
199 if(cinfo->authenticate == "document")
200 {
201 // both are either commented out or uncomment and are empty
202 if (cinfo->public_documents.empty() && cinfo->private_documents.empty())
203 {
204 //deny everything
205 args["uan"] = "1";
206 args["ug"] = cinfo->auth_group;
207 }
208
209 // both public_documents and private_documents are turned on !
210 else if (!cinfo->public_documents.empty() && !cinfo->private_documents.empty())
211 {
212 //deny everything
213 args["uan"] = "1";
214 args["ug"] = cinfo->auth_group;
215 }
216
217 // if public_documents is set but this document isn't
218 // listed in it we need to authenticate
219 else if ((!cinfo->public_documents.empty()) &&
220 (cinfo->public_documents.find(docTop) == cinfo->public_documents.end()))
221 {
222 args["uan"] = "1";
223 args["ug"] = cinfo->auth_group;
224 }
225
226 // if private_documents is set and this document is
227 // listed in it we need to authenticate
228 else if ((!cinfo->private_documents.empty()) &&
229 (cinfo->private_documents.find(docTop) != cinfo->private_documents.end()))
230 {
231 args["uan"] = "1";
232 args["ug"] = cinfo->auth_group;
233 }
234
235 }
236 }
237 }
238 // check gc argument
239 int arg_gc = args.getintarg("gc");
240 if (arg_gc < 0 || arg_gc > 2) {
241 logout << "Warning: \"gc\" argument out of range (" << arg_gc << ")\n";
242 cgiarginfo *gcinfo = argsinfo.getarginfo ("gc");
243 if (gcinfo != NULL) args["gc"] = gcinfo->argdefault;
244 }
245
246 // check gt argument (may be either 0, 1 or 2)
247 int arg_gt = args.getintarg("gt");
248 if (arg_gt != 0 && arg_gt != 1 && arg_gt != 2) {
249 logout << "Warning: \"gt\" argument out of range (" << arg_gt << ")\n";
250 cgiarginfo *gtinfo = argsinfo.getarginfo ("gt");
251 if (gtinfo != NULL) args["gt"] = gtinfo->argdefault;
252 }
253
254 // check hl argument
255 int arg_hl = args.getintarg("hl");
256 if (arg_hl < 0 || arg_hl > 2) {
257 logout << "Warning: \"hl\" argument out of range (" << arg_hl << ")\n";
258 cgiarginfo *hlinfo = argsinfo.getarginfo ("hl");
259 if (hlinfo != NULL) args["hl"] = hlinfo->argdefault;
260 }
261
262 // check x argument
263 int arg_x = args.getintarg("x");
264 if (arg_x != 0 && arg_x != 1) {
265 logout << "Warning: \"x\" argument out of range (" << arg_x << ")\n";
266 cgiarginfo *xinfo = argsinfo.getarginfo ("x");
267 if (xinfo != NULL) args["x"] = xinfo->argdefault;
268 }
269
270 //checks whether rd arg is valid
271 int arg_rd = args.getintarg("rd");
272 if (arg_rd != 0 && arg_rd != 1) {
273 logout << "Warning: \"rd\" argument out of range (" << arg_rd << ")\n";
274 cgiarginfo *rdinfo = argsinfo.getarginfo ("rd");
275 if (rdinfo != NULL) args["rd"] = rdinfo->argdefault;
276 }
277
278
279 return true;
280}
281
282void documentaction::get_cgihead_info (cgiargsclass &args, recptprotolistclass *protos,
283 response_t &response,text_t &response_data,
284 ostream &logout) {
285
286 if ((args["il"] == "w") && (!args["d"].empty())) {
287
288 recptproto* collectproto = protos->getrecptproto (args["c"], logout);
289 if (collectproto != NULL) {
290
291 text_tset metadata;
292 FilterResponse_t filt_response;
293 text_t top;
294
295 metadata.insert ("URL");
296
297 // get metadata for parent document
298 get_top (args["d"], top);
299 if (get_info (top, args["c"], args["l"], metadata, false, collectproto, filt_response, logout)) {
300 text_t url = filt_response.docInfo[0].metadata["URL"].values[0];
301
302 response = location;
303 response_data = url;
304 return;
305 } else {
306 // error, no URL
307 logout << "Error: documentaction::get_cgihead_info failed on get_info" << endl;
308 }
309 }
310 }
311 response = content;
312 response_data = "text/html";
313}
314
315// set_widthtspace calculates how wide the spaces in the nav bar should
316// be and sets the appropriate macro
317void documentaction::set_spacemacro (displayclass &disp, FilterResponse_t &response,
318 bool has_search_button) {
319
320 text_t width;
321 int twidth, swidth, iwidth = 0;
322
323 int numc = response.docInfo.size();
324 ResultDocInfo_tarray::iterator dochere = response.docInfo.begin();
325 ResultDocInfo_tarray::iterator docend = response.docInfo.end();
326
327 disp.expandstring (displayclass::defaultpackage, "_pagewidth_", width);
328 twidth = width.getint();
329
330 if (has_search_button) {
331 disp.expandstring ("query", "_searchwidth_", width);
332 iwidth += width.getint();
333 } else {
334 numc -= 1;
335 }
336
337 while (dochere != docend) {
338 const text_t &title = (*dochere).metadata["Title"].values[0];
339
340 disp.expandstring ("document", "_" + title + "width_", width);
341 if (width == ("_" + title + "width_")) {
342 disp.expandstring ("document", "_defaultwidth_", width);
343 }
344 iwidth += width.getint();
345 ++dochere;
346 }
347
348 if ((twidth - iwidth) < numc) swidth = 2;
349 else {
350 swidth = twidth - iwidth;
351 if (numc > 0) swidth = swidth / numc;
352 }
353 disp.setmacro ("widthtspace", displayclass::defaultpackage, swidth);
354}
355
356// set_navbarmacros sets _navigationbar_ and _httpbrowseXXX_ macros
357// reponse contains 1 metadata field (Title)
358void documentaction::set_navbarmacros (displayclass &disp, FilterResponse_t &response,
359 bool has_search_button, cgiargsclass &args,
360 ColInfoResponse_t &cinfo) {
361
362
363 bool use_pulldown = false;
364 text_tmap::iterator it = cinfo.format.find("NavigationBar");
365 if (it != cinfo.format.end()) {
366 if (it->second == "pulldown") {
367 use_pulldown = true;
368 }
369 }
370
371 text_t topparent;
372 text_t &arg_d = args["d"];
373 text_t navigationbar = "<!-- Navigation Bar -->\n";
374
375 get_top (args["cl"], topparent);
376 int numc = response.docInfo.size();
377 ResultDocInfo_tarray::iterator dochere = response.docInfo.begin();
378 ResultDocInfo_tarray::iterator docend = response.docInfo.end();
379
380 if (!use_pulldown) {
381 if (has_search_button) {
382 // search uses its own navtab, as it may be suppressed based on args
383 navigationbar += "_navtabsearch_";
384 if (args["a"] == "q") {
385 navigationbar += "(selected)";
386 }
387 }
388
389 if (has_search_button || numc == 0) navigationbar += "_navbarspacer_";
390
391 bool first = true;
392 while (dochere != docend) {
393 if (!first) navigationbar += "_navbarspacer_";
394
395 text_t title = (*dochere).metadata["Title"].values[0];
396
397 navigationbar += "_navtab_(_httpbrowse"+title+"_,"+title;
398 // if we are at this classifier
399 if (arg_d.empty() && ((*dochere).OID == topparent)) {
400 // don't link to this classifier as it is the current one
401 navigationbar += ",selected";
402 }
403 navigationbar += ")";
404
405 // set the _httpbrowseXXX_ macro for this classification
406 // set the correct url for this link
407 disp.setmacro ("httpbrowse" + title, displayclass::defaultpackage, "_httpdocument_&amp;cl=" + (*dochere).OID);
408 ++dochere;
409 first = false;
410 }
411
412 navigationbar += "\n<!-- End of Navigation Bar -->\n";
413
414 } else {
415
416 navigationbar = "<form method=\"get\" name=\"navform\">\n";
417 navigationbar += "<select name=\"navbar\" onChange=\"location.href=";
418 navigationbar += "document.navform.navbar.options[document.navform.navbar.selectedIndex].value\">\n";
419
420 if (args["a"] != "q" && args["cl"].empty()) {
421 navigationbar += "<option value=\"\" selected>_textselectpage_</option>\n";
422 }
423
424 if (has_search_button) {
425 navigationbar += "<option value=\"_httpquery_\"";
426 if (args["a"] == "q") {
427 navigationbar += " selected";
428 }
429 navigationbar += ">_labelSearch_</option>\n";
430 }
431
432 while (dochere != docend) {
433 text_t title = dochere->metadata["Title"].values[0];
434
435 navigationbar += "<option value=\"_httpdocument_&amp;cl=" + dochere->OID + "\"";
436 if (topparent == dochere->OID) {
437 navigationbar += " selected";
438 }
439 navigationbar += ">_navlinktitle_(" + title + ")</option>\n";
440 ++dochere;
441 }
442
443 navigationbar += "</select>\n";
444 navigationbar += "</form>\n";
445 }
446
447 disp.setmacro ("navigationbar", displayclass::defaultpackage, navigationbar);
448}
449
450// define all the macros which might be used by other actions
451// to produce pages.
452void documentaction::define_external_macros (displayclass &disp, cgiargsclass &args,
453 recptprotolistclass *protos, ostream &logout) {
454
455 // define_external_macros sets the following macros:
456
457 // _navigationbar_ this is the navigation bar containing the search button
458 // and any classification buttons - it goes at the top of
459 // most pages. for now we're assuming that there'll always
460 // be a search button - we should probably check that there
461 // is a query action before making this assumption
462
463 // _httpbrowseXXX_ the http macros for each classification (i.e. if there
464 // are Title and Creator classifications _httpbrowseTitle_
465 // and _httpbrowseCreator_ will be set
466
467 // _widthtspace_ the width of the spacers between buttons in navigation
468 // bar
469
470 // _httpdocument_ has '&f=1' added if displaying document inside a frame
471
472 // _gsdltop_ macro to replace _top targets with
473
474 // _httppagehome_ overridden home url if html collections have own homepage
475
476 // _usability_ macros for remote usability reporting: if
477 // _usabinterface_ "format Usability [multi|textonly|stepwise]" is in
478 // _usabilityscript_ collect.cfg
479
480 // must have a valid collection server to continue
481
482 text_t &collection = args["c"];
483 if (collection.empty()) return;
484 recptproto *collectproto = protos->getrecptproto (collection, logout);
485 if (collectproto == NULL) return;
486
487 if (recpt == NULL) {
488 logout << "ERROR (documentaction::define_external_macros): This action does not contain\n"
489 << " information about any receptionists. The method set_receptionist was\n"
490 << " probably not called from the module which instantiated this action.\n";
491 return;
492 }
493
494 outconvertclass text_t2ascii;
495 comerror_t err;
496 InfoFiltersResponse_t filterinfo;
497 FilterResponse_t response;
498 text_tset metadata;
499
500 // get info on current collection and load up formatinfo
501 // I'd prefer not to do this here as we're getting
502 // collection info every time (and probably also getting
503 // it in other places some of the time) - One day I'll
504 // fix it ... maybe - Stefan.
505 ColInfoResponse_t cinfo;
506
507 collectproto->get_collectinfo (collection, cinfo, err, logout);
508 load_formatinfo (cinfo.format, args.getintarg("gt"));
509 // ColInfoResponse_t *cinfo = recpt->get_collectinfo_ptr (collectproto, collection, logout);
510 // if (cinfo == NULL) {
511 // logout << "ERROR (documentaction::define_external_macros): get_collectinfo_ptr returned NULL\n";
512 // return;
513 // }
514 //load_formatinfo (cinfo->format, args.getintarg("gt"));
515
516 if (formatinfo.DocumentUseHTML) {
517
518 // frame stuff
519 if (args["fc"] == "1") {
520 text_t httpdocument;
521 disp.expandstring (displayclass::defaultpackage, "_httpdocument_", httpdocument);
522 httpdocument += "&amp;f=1";
523 disp.setmacro ("httpdocument", displayclass::defaultpackage, httpdocument);
524 disp.setmacro ("gsdltop", displayclass::defaultpackage, "documenttop");
525 formatinfo.DocumentText = "[Text]";
526 }
527 text_tmap::iterator it = cinfo.format.find ("homepage");
528 if (it != cinfo.format.end()) {
529 text_t httppagehome;
530 if (get_link (args, protos, (*it).second, httppagehome, logout))
531 disp.setmacro ("httppagehome", displayclass::defaultpackage, httppagehome);
532 }
533 }
534
535 // don't want navigation bar if page is 'detached'
536 if (!args.getintarg("x")) {
537
538 collectproto->get_filterinfo (collection, filterinfo, err, logout);
539 if (err == noError) {
540 // check that there's a browse filter
541 if (filterinfo.filterNames.find ("BrowseFilter") != filterinfo.filterNames.end()) {
542
543 metadata.insert ("Title");
544 bool getParents = false;
545 get_children ("", collection, args["l"], metadata, getParents, collectproto, response, logout);
546
547 bool has_search_button = true;
548 collectproto->is_searchable(collection, has_search_button, err, logout);
549 if (err != noError) has_search_button = false;
550
551 // calculate width of spacers and set _widthtspace_ macro
552 if (args.getintarg("v") == 0) set_spacemacro (disp, response, has_search_button);
553
554 // set _navigationbar_ macro
555 set_navbarmacros (disp, response, has_search_button, args, cinfo);
556
557 }
558 } else {
559 logout << text_t2ascii
560 << "Error (documentaction::define_external_macros()) in call to get_filterinfo() "
561 << get_comerror_string (err);
562 }
563 }
564
565 // send feedback button and pages
566 text_tmap::iterator usability = cinfo.format.find("Usability");
567 if(usability!=cinfo.format.end()){
568 disp.setmacro("usability",displayclass::defaultpackage,"_usablink_");
569 disp.setmacro("usabinterface",displayclass::defaultpackage,("_usab"+(*usability).second+"_"));
570 disp.setmacro("usabilityscript", displayclass::defaultpackage, "_usabshowscript_");
571 }
572
573}
574
575bool documentaction::get_link (cgiargsclass &args, recptprotolistclass *protos,
576 const text_t &inlink, text_t &outlink, ostream &logout) {
577
578 FilterResponse_t response;
579 text_tset metadata;
580 metadata.insert ("section");
581
582 // check current collection first
583 recptproto *collectproto = protos->getrecptproto (args["c"], logout);
584
585 if (get_info (inlink, args["c"], args["l"], metadata, false, collectproto, response, logout)) {
586 if (!response.docInfo[0].metadata["section"].values[0].empty()) {
587#ifndef DOCHANDLE
588 outlink = "_httpdocument_&amp;d=" + response.docInfo[0].metadata["section"].values[0];
589#else
590 outlink = "_httpdocumenthandle_("+args["c"]+","+response.docInfo[0].metadata["section"].values[0]+")";
591#endif
592
593 return true;
594 }
595 }
596
597 // check all the other enabled collections
598
599 if (args["ccs"] == "1" && !args["cc"].empty()) {
600 text_tarray collections;
601 splitchar (args["cc"].begin(), args["cc"].end(), ',', collections);
602
603 text_tarray::const_iterator col_here = collections.begin();
604 text_tarray::const_iterator col_end = collections.end();
605
606 while (col_here != col_end) {
607
608 // don't need to check current collection again
609 if (*col_here == args["c"]) {++col_here; continue;}
610
611 collectproto = protos->getrecptproto (*col_here, logout);
612
613 if (get_info (inlink, *col_here, args["l"], metadata, false, collectproto, response, logout)) {
614 if (!response.docInfo[0].metadata["section"].values[0].empty()) {
615#ifndef DOCHANDLE
616 outlink = "_httpdocument_&amp;c=" + *col_here + "&amp;d=" +
617 response.docInfo[0].metadata["section"].values[0];
618#else
619 outlink = "_httpdocumenthandle_("+*col_here+","+response.docInfo[0].metadata["section"].values[0]+")";
620#endif
621
622 return true;
623 }
624 }
625 ++col_here;
626 }
627 }
628 return false;
629}
630
631void documentaction::load_formatinfo (const text_tmap &colformat, int gt) {
632
633 formatinfo.clear();
634 text_tmap::const_iterator format_here = colformat.begin();
635 text_tmap::const_iterator format_end = colformat.end();
636
637 while (format_here != format_end) {
638 if (((*format_here).first == "DocumentImages") &&
639 ((*format_here).second == "true"))
640 formatinfo.DocumentImages = true;
641 else if (((*format_here).first == "DocumentTitles") &&
642 ((*format_here).second == "false"))
643 formatinfo.DocumentTitles = false;
644 else if ((*format_here).first == "DocumentHeading")
645 formatinfo.DocumentHeading = (*format_here).second;
646 else if (((*format_here).first == "DocumentContents") &&
647 ((*format_here).second == "false"))
648 formatinfo.DocumentContents = false;
649 else if (((*format_here).first == "DocumentArrowsBottom") &&
650 ((*format_here).second == "false"))
651 formatinfo.DocumentArrowsBottom = false;
652 else if (((*format_here).first == "DocumentArrowsTop") &&
653 ((*format_here).second == "true"))
654 formatinfo.DocumentArrowsTop = true;
655 else if ((*format_here).first == "DocumentButtons")
656 splitchar ((*format_here).second.begin(), (*format_here).second.end(),
657 '|', formatinfo.DocumentButtons);
658 else if ((*format_here).first == "DocumentText")
659 formatinfo.DocumentText = (*format_here).second;
660 else if ((*format_here).first == "RelatedDocuments")
661 formatinfo.RelatedDocuments = (*format_here).second;
662 else if (((*format_here).first == "DocumentUseHTML") &&
663 ((*format_here).second == "true"))
664 formatinfo.DocumentUseHTML = true;
665 else if (((*format_here).first == "AllowExtendedOptions") &&
666 ((*format_here).second == "true"))
667 formatinfo.AllowExtendedOptions = true;
668 else
669 formatinfo.formatstrings[(*format_here).first] = (*format_here).second;
670
671 ++format_here;
672 }
673
674 // never want arrows when text is expanded
675 if (gt) {
676 formatinfo.DocumentArrowsBottom = false;
677 formatinfo.DocumentArrowsTop = false;
678 }
679}
680
681
682// define all the macros which are related to pages generated
683// by this action. we also load up the formatinfo structure
684// here (it's used in do_action as well as here)
685void documentaction::define_internal_macros (displayclass &disp, cgiargsclass &args,
686 recptprotolistclass *protos, ostream &logout) {
687
688 // define_internal_macros sets the following macros:
689
690 // _pagetitle_ the title to be displayed at the top of the browser window
691
692 // _imagethispage_ the title image to be displayed at top right of page
693
694 // _navarrowsbottom_ this may be overridden to "" when format option
695 // DocumentArrowsBottom is false
696
697 // _navarrowstop_ likewise for DocumentArrowsTop
698
699 // _httpprevarrow_ links to next and previous sections of document - used
700 // _httpnextarrow_ by DocumentArrowsBottom
701
702 // _header_ the header macro is overridden if we're not at a top level
703 // classification to remove the title block
704
705 // _thisOID_ the OID (directory) of the current document - this corresponds
706 // to the archivedir metadata element
707
708 // must have a valid collection server to continue
709
710 text_t &collection = args["c"];
711 if (collection.empty()) return;
712 recptproto *collectproto = protos->getrecptproto (collection, logout);
713 if (collectproto == NULL) return;
714
715 text_tset metadata;
716 FilterResponse_t response;
717 text_t &arg_d = args["d"];
718 text_t &arg_cl = args["cl"];
719
720 if (!formatinfo.DocumentArrowsBottom) {
721 disp.setmacro("navarrowsbottom", "document", "");
722 } else if (!formatinfo.DocumentArrowsBottom) {
723 disp.setmacro("navarrowstop", "document", "");
724 }
725
726 if (!arg_d.empty() && (formatinfo.DocumentArrowsBottom || formatinfo.DocumentArrowsTop)) {
727 // set _httpprevarrow_ and _httpnextarrow_
728 set_arrow_macros (args, collectproto, disp, logout);
729 }
730
731 metadata.insert ("Title");
732
733 bool fulltoc = false;
734
735 if (args["cl"] != "search") {
736 // see if there's a FullTOC string
737 text_t cl_top, full_toc;
738 get_top (arg_cl, cl_top);
739 if (get_formatstring (cl_top, "FullTOC", formatinfo.formatstrings, full_toc))
740 if (full_toc == "true") fulltoc = true;
741 }
742
743 if (!arg_d.empty() && !fulltoc) {
744 // we're at document level
745
746 metadata.insert ("archivedir");
747
748 comerror_t err;
749 OptionValue_tarray options;
750 // we need to do the query again for the z3950proto
751 if (collectproto->get_protocol_name(err)=="z3950proto") {
752 OptionValue_t opt;
753 opt.name="Term";opt.value=args["q"];options.push_back(opt);
754 opt.name="QueryType";
755 opt.value=(args.getintarg("t")) ? "ranked" : "boolean";
756 options.push_back(opt);
757 opt.name="Index";opt.value=args["h"];options.push_back(opt);
758 }
759
760 //do not display relation metadata
761 disp.setmacro ("relateddoc", "document", "");
762
763 //if preferences indicate relevant docs should be collected
764 //and there is no particular format specified then display
765 //this default format.
766 if(args["rd"] == "1" && formatinfo.RelatedDocuments.empty()){
767
768 text_t relation = g_EmptyText; //string for displaying relation metadata
769
770 //call function in formattools.cpp which will return the text of the
771 //related documents in a vertical list. This is the default format.
772
773 if (get_info (arg_d, collection, args["l"], metadata, options, false, collectproto, response, logout))
774 relation += get_related_docs(collection, collectproto, response.docInfo[0], logout);
775
776 //set macro to be the related document string
777
778 disp.setmacro ("relateddoc", "document", relation);
779 }
780
781
782 // get metadata for this document and it's parents
783 if (get_info (arg_d, collection, args["l"], metadata, options,
784 true, collectproto, response, logout)) {
785
786 disp.setmacro ("header", "document", "_textheader_");
787
788 text_tarray pagetitlearray;
789 if (!response.docInfo[0].metadata["Title"].values[0].empty())
790 pagetitlearray.push_back (response.docInfo[0].metadata["Title"].values[0]);
791
792 if (args["gt"] != "1") {
793 MetadataInfo_t *parenttitle = response.docInfo[0].metadata["Title"].parent;
794 while (parenttitle != NULL) {
795 if (!parenttitle->values[0].empty())
796 pagetitlearray.push_back (parenttitle->values[0]);
797 parenttitle = parenttitle->parent;
798 }
799 }
800 reverse (pagetitlearray.begin(), pagetitlearray.end());
801 text_t pagetitle;
802 joinchar (pagetitlearray, ": ", pagetitle);
803 // remove html tags from the title
804 text_t::iterator open_tag=pagetitle.begin();
805 while (open_tag < pagetitle.end()) {
806 if (*open_tag == '<') {
807 text_t::iterator close_tag=open_tag+1;
808 text_t::iterator donechar=pagetitle.end();
809 while (close_tag < donechar) {
810 if (*close_tag == '>')
811 break;
812 ++close_tag;
813 }
814 if (close_tag < donechar) // remove this html tag, replace with space
815 *close_tag=' ';
816 pagetitle.erase(open_tag, close_tag);
817 }
818 ++open_tag;
819 }
820 disp.setmacro ("pagetitle", "document", pagetitle);
821
822 if (is_top (arg_d))
823 disp.setmacro ("thisOID", displayclass::defaultpackage, dm_safe(response.docInfo[0].metadata["archivedir"].values[0]));
824 else {
825 MetadataInfo_t *parentad = response.docInfo[0].metadata["archivedir"].parent;
826 text_t thisOID;
827 while (parentad != NULL) {
828 thisOID = parentad->values[0];
829 parentad = parentad->parent;
830 }
831 disp.setmacro ("thisOID", displayclass::defaultpackage, dm_safe(thisOID));
832 }
833 }
834 } else {
835 if (!arg_cl.empty()) {
836
837 // create the currentnodevalue macro - this is the value of the node
838 // in the hierarchy that is currently open.
839 if (get_info (arg_cl, collection, args["l"], metadata, false, collectproto, response, logout)) {
840 text_t &title = response.docInfo[0].metadata["Title"].values[0];
841 disp.setmacro ("currentnodevalue", "document", title);
842 }
843 // get metadata for top level classification
844 text_t classtop;
845 get_top (arg_cl, classtop);
846 metadata.insert ("childtype");
847 metadata.insert ("parameters");
848
849 if (get_info (classtop, collection, args["l"], metadata, false, collectproto, response, logout)) {
850
851 text_t &title = response.docInfo[0].metadata["Title"].values[0];
852 bool unknown = false;
853
854 // test if we have macros defined for this classification's
855 // metadata name - if not we'll just display the name
856 text_t tmp;
857 text_t macroname="_label" + title + "_";
858 disp.expandstring ("Global", macroname, tmp);
859 if (tmp == macroname) unknown = true; // it wasn't expanded
860
861 if (unknown) {
862 disp.setmacro ("pagetitle", "document", title);
863 } else {
864 disp.setmacro ("pagetitle", "document", macroname);
865 }
866 /* for ns4/image layout compatibility. when this is no longer
867 * needed, set imagethispage to _label+title+_ */
868 text_t titlemacroname="_titleimage" + title + "_";
869 disp.expandstring ("Global", titlemacroname, tmp);
870 if (tmp == titlemacroname) { /* _titleimage$META_ isn't defined */
871 if (!unknown) /* _label$META_ is defined */
872 disp.setmacro ("imagethispage", "document", macroname);
873 else
874 disp.setmacro ("imagethispage", "document", title);
875 } else { /* _titleimage$META_ is defined */
876 disp.setmacro ("imagethispage", "document", titlemacroname);
877 }
878
879 //if the document is not a document from a collection
880 //we must set the macro to be an empty string
881 disp.setmacro ("relateddoc", "document", "");
882
883 // Add macros specific to the Collage/Phind classifiers
884 text_t &childtype = response.docInfo[0].metadata["childtype"].values[0];
885 if (childtype == "Collage") {
886
887 text_t::iterator a = arg_cl.begin();
888 text_t::iterator b = arg_cl.end();
889
890 bool collage = true;
891 while (a != b) {
892 if (*a == 46) collage = false;
893 ++a;
894 }
895
896 if (collage) {
897 disp.setmacro ("collageclassifier", "document", "_collageapplet_");
898
899 // Next, macros that control the way the classifier is displayed
900 text_t parameters = response.docInfo[0].metadata["parameters"].values[0];
901
902 // extract key=value pairs and set as macros
903 text_t::iterator here = parameters.begin();
904 text_t::iterator end = parameters.end();
905 text_t key, value;
906
907 while (here != end) {
908 // get the next key and value pair
909 here = getdelimitstr (here, end, '=', key);
910 here = getdelimitstr (here, end, ';', value);
911
912 // store this key=value pair
913 if (!key.empty() && !value.empty()) {
914 disp.setmacro ("collage"+key, "document", value);
915 }
916 }
917
918
919 }
920 }
921
922 if (childtype == "Phind") {
923
924 // First, a macro to display the phind classifier
925 disp.setmacro ("phindclassifier", "document", "_phindapplet_");
926
927 // Next, macros that control the way the classifier is displayed
928 text_t parameters = response.docInfo[0].metadata["parameters"].values[0];
929
930 // extract key=value pairs and set as macros
931 text_t::iterator here = parameters.begin();
932 text_t::iterator end = parameters.end();
933 text_t key, value;
934
935 while (here != end) {
936 // get the next key and value pair
937 here = getdelimitstr (here, end, '=', key);
938 here = getdelimitstr (here, end, ';', value);
939
940 // store this key=value pair
941 if (!key.empty() && !value.empty()) {
942 disp.setmacro (key, "document", value);
943 }
944 }
945 } // end if (childtype == "Phind")
946 }
947 } // end if (!arg_cl.empty()) {
948 }
949}
950
951
952bool documentaction::do_action(cgiargsclass &args, recptprotolistclass *protos,
953 browsermapclass *browsers, displayclass &disp,
954 outconvertclass &outconvert, ostream &textout,
955 ostream &logout)
956{
957 // must have a valid collection server
958 recptproto *collectproto = protos->getrecptproto (args["c"], logout);
959 if (collectproto == NULL) {
960 logout << "documentaction::do_action called with NULL collectproto\n";
961 textout << outconvert << disp << "_document:header_\n"
962 << "Error: Attempt to get document without setting collection\n"
963 << "_document:footer_\n";
964 } else {
965
966 text_t OID = args["d"];
967 if (OID.empty()) OID = args["cl"];
968 if (OID.empty()) {
969 textout << outconvert << disp << "Document contains no data_document:footer_\n";
970 return true;
971 }
972
973
974 if (formatinfo.DocumentUseHTML && !args["d"].empty()) {
975
976 if (args["f"] == "1") {
977 textout << outconvert << disp
978 << "<html><head></head>\n"
979 << "<frameset rows=\"68,*\" noresize border=0>\n"
980 << "<frame scrolling=no frameborder=0 src=\"_gwcgi_?_optsite_e=_compressedoptions_&a=p&p=nav\">\n"
981#ifndef DOCHANDLE
982 << "<frame name=\"documenttop\" frameborder=0 src=\"_gwcgi_?_optsite_e=_compressedoptions_&a=d&d="
983 << args["d"] << "\">"
984#else
985 << "<frame name=\"documenttop\" frameborder=0 src=\"_httpdocumenthandle_("
986 << args["c"] << "," << args["d"] << ")\">"
987#endif
988 << "<noframes>\n"
989 << "<p>You must have a frame enabled browser to view this.</p>\n"
990 << "</noframes>\n"
991 << "</frameset>\n"
992 << "</html>\n";
993 } else {
994 output_document (OID, args, collectproto, browsers, disp, outconvert, textout, logout);
995 }
996 return true;
997 }
998
999
1000 textout << outconvert << disp << "_document:header_\n"
1001 << "_document:content_\n";
1002
1003 // output the table of contents
1004 browsetoolsclass b;
1005 b.output_toc(args, browsers, formatinfo, collectproto,
1006 disp, outconvert, textout, logout);
1007
1008 if (formatinfo.DocumentArrowsTop && !args["d"].empty()) {
1009 textout << outconvert << disp << "_document:navarrowstop_\n";
1010 }
1011
1012 //output the related documents (may be the empty string)
1013 //will not output the docs if a format string is specified
1014 textout << outconvert << disp << "_document:relateddoc_\n";
1015
1016 // output the document text
1017 if (!args["d"].empty()) {
1018 textout << outconvert << "<p>\n";
1019 output_document (OID, args, collectproto, browsers, disp, outconvert, textout, logout);
1020 }
1021
1022 textout << outconvert << disp << "_document:footer_\n";
1023 }
1024 return true;
1025}
1026
1027void documentaction::output_text (ResultDocInfo_t &docinfo, format_t *formatlistptr,
1028 const TermInfo_tarray &terminfo, const text_t &OID,
1029 bool highlight, int hastxt, int wanttext,
1030 text_t &collection, recptproto *collectproto,
1031 browsermapclass *browsers, displayclass &disp,
1032 outconvertclass &outconvert, ostream &textout,
1033 ostream &logout, cgiargsclass &args) {
1034
1035 DocumentRequest_t docrequest;
1036 DocumentResponse_t docresponse;
1037 comerror_t err;
1038 if (hastxt == 1) {
1039
1040 if (wanttext) {
1041 // get the text
1042 docrequest.OID = OID;
1043 collectproto->get_document (collection, docrequest, docresponse, err, logout);
1044
1045 // cut down on overhead by not using formattools if we only want the text
1046 // (wanttext will equal 2 if we want text and other stuff too)
1047 if (wanttext == 1)
1048 if (highlight) {
1049 highlighttext(docresponse.doc, args, terminfo, disp, outconvert, textout);
1050 } else {
1051 textout << outconvert << disp << docresponse.doc;
1052 }
1053 }
1054
1055 if (wanttext != 1) {
1056 text_tmap options;
1057 options["text"] = docresponse.doc;
1058
1059 if (formatinfo.AllowExtendedOptions) {
1060 browsetoolsclass b;
1061 b.load_extended_options(options, args, browsers, formatinfo,
1062 collectproto, disp, outconvert, logout);
1063 }
1064
1065 text_t doctext
1066 = get_formatted_string (collection, collectproto, docinfo, disp,
1067 formatlistptr, options, logout);
1068
1069 if (highlight) {
1070 highlighttext(doctext, args, terminfo, disp, outconvert, textout);
1071 } else {
1072 textout << outconvert << disp << doctext;
1073 }
1074 }
1075 }
1076}
1077
1078
1079void documentaction::output_document (const text_t &OID, cgiargsclass &args,
1080 recptproto *collectproto, browsermapclass *browsers,
1081 displayclass &disp, outconvertclass &outconvert,
1082 ostream &textout, ostream &logout) {
1083 FilterResponse_t inforesponse;
1084 FilterResponse_t queryresponse;
1085 text_tset metadata;
1086 bool getParents = false;
1087 bool highlight = false;
1088 int wanttext = 0;
1089 int arg_gt = args.getintarg("gt");
1090 text_t &collection = args["c"];
1091
1092 // if we have a query string and highlighting is turned on we need
1093 // to redo the query to get the terms for highlighting
1094
1095 if (!args["q"].empty() && args.getintarg("hl")) {
1096
1097 ColInfoResponse_t *cinfo = recpt->get_collectinfo_ptr (collectproto, collection, logout);
1098 bool segment = false;
1099 if (cinfo != NULL) {
1100 segment = cinfo->isSegmented;
1101 }
1102 FilterRequest_t request;
1103 comerror_t err;
1104 request.filterResultOptions = FRmatchTerms;
1105 text_t formattedstring = args["q"];
1106 format_querystring (formattedstring, args.getintarg("b"), segment);
1107 set_queryfilter_options (request, formattedstring, args);
1108 args["q"] = formattedstring; // need to set this here for phrase
1109 // highlighting, where we look at the querystring
1110 collectproto->filter (args["c"], request, queryresponse, err, logout);
1111 if (err != noError) {
1112 outconvertclass text_t2ascii;
1113 logout << text_t2ascii
1114 << "documentaction::output_document: call to QueryFilter failed "
1115 << "for " << args["c"] << " collection (" << get_comerror_string (err) << ")\n";
1116 highlight = false;
1117 } else {
1118 highlight = true;
1119 }
1120 }
1121
1122 format_t *formatlistptr = new format_t();
1123 parse_formatstring (formatinfo.DocumentText, formatlistptr, metadata, getParents);
1124
1125 metadata.insert ("hastxt");
1126 metadata.insert ("haschildren");
1127
1128 if (formatinfo.DocumentText == "[Text]")
1129 wanttext = 1;
1130 else {
1131 char *docformat = formatinfo.DocumentText.getcstr();
1132 if (strstr (docformat, "[Text]") != NULL)
1133 wanttext = 2;
1134 delete []docformat;
1135 }
1136
1137 textout << outconvert << "<div class=\"documenttext\">\n";
1138
1139 if (get_info (OID, collection, args["l"], metadata, getParents, collectproto, inforesponse, logout)) {
1140 int hastxt = inforesponse.docInfo[0].metadata["hastxt"].values[0].getint();
1141 int haschildren = inforesponse.docInfo[0].metadata["haschildren"].values[0].getint();
1142
1143 if (arg_gt == 0) {
1144 output_text (inforesponse.docInfo[0], formatlistptr, queryresponse.termInfo,
1145 OID, highlight, hastxt, wanttext, collection, collectproto,
1146 browsers, disp, outconvert, textout, logout, args);
1147
1148 } else {
1149
1150 ResultDocInfo_t thisdocinfo = inforesponse.docInfo[0];
1151
1152 // text is to be expanded
1153 text_t exOID = OID;
1154 if (haschildren != 1) exOID = get_parent (OID);
1155 if (exOID.empty()) exOID = OID;
1156
1157 // if we're not in a document (i.e. we're in a top level classification)
1158 // we need to pass "is_classify = true" to get_contents so that it
1159 // doesn't recurse all the way through each document in the classification
1160 bool is_classify = false;
1161 if (args["d"].empty()) is_classify = true;
1162
1163 get_contents (exOID, is_classify, metadata, collection, args["l"],
1164 collectproto, inforesponse, logout);
1165
1166 ResultDocInfo_tarray::iterator sechere = inforesponse.docInfo.begin();
1167 ResultDocInfo_tarray::iterator secend = inforesponse.docInfo.end();
1168
1169 if (arg_gt == 1) {
1170 // check if there are more than 10 sections containing text to be expanded -
1171 // if there are output warning message - this isn't a great way to do this
1172 // since the sections may be very large or very small - one day I'll fix it
1173 // -- Stefan.
1174 int seccount = 0;
1175 while (sechere != secend) {
1176 int shastxt = (*sechere).metadata["hastxt"].values[0].getint();
1177 if (shastxt == 1) ++seccount;
1178 if (seccount > 10) break;
1179 ++sechere;
1180 }
1181 if (seccount > 10) {
1182 // more than 10 sections so output warning message and text
1183 // for current section only
1184 textout << outconvert << disp << "<div class=\"warning\">_document:textltwarning_</div>\n";
1185
1186 output_text (thisdocinfo, formatlistptr, queryresponse.termInfo,
1187 OID, highlight, hastxt, wanttext, collection,
1188 collectproto, browsers, disp, outconvert, textout, logout, args);
1189
1190 }
1191 else arg_gt = 2;
1192 }
1193
1194 if (arg_gt == 2) {
1195 // get the text for each section
1196 sechere = inforesponse.docInfo.begin();
1197 int count = 0;
1198 while (sechere != secend) {
1199 textout << outconvert << disp << "\n<p><a name=" << (*sechere).OID << "></a>\n";
1200
1201 int shastxt = (*sechere).metadata["hastxt"].values[0].getint();
1202
1203 output_text (*sechere, formatlistptr, queryresponse.termInfo,
1204 (*sechere).OID, highlight, shastxt, wanttext, collection,
1205 collectproto, browsers, disp, outconvert, textout, logout, args);
1206 ++count;
1207 ++sechere;
1208 }
1209 }
1210 }
1211 }
1212 textout << outconvert << "</div>\n";
1213 delete formatlistptr;
1214}
1215
1216void documentaction::set_arrow_macros (cgiargsclass &args, recptproto *collectproto,
1217 displayclass &disp, ostream &logout) {
1218
1219 text_tset metadata;
1220 FilterResponse_t response;
1221 FilterResponse_t presponse;
1222
1223 int haschildren = 0;
1224 text_tarray next_siblings;
1225 text_t previous_sibling;
1226 text_t &arg_d = args["d"];
1227
1228 // get info on current section
1229 metadata.insert("haschildren");
1230 if (!get_info(arg_d, args["c"], args["l"], metadata, false, collectproto, response, logout)) {
1231 logout << "error 1 in documentaction::set_arrow_macros\n";
1232 return;
1233 }
1234 haschildren = response.docInfo[0].metadata["haschildren"].values[0].getint();
1235
1236 // get OIDs of next and previous siblings of current section and
1237 // all it's parents
1238 int parentcount = countchar(arg_d.begin(), arg_d.end(), '.');
1239 text_t thisoid = arg_d;
1240 while (parentcount > 0) {
1241 get_children (get_parent(thisoid), args["c"], args["l"], metadata, false,
1242 collectproto, response, logout);
1243 ResultDocInfo_tarray::iterator this_sibling = response.docInfo.begin();
1244 ResultDocInfo_tarray::iterator last_sibling = response.docInfo.end();
1245 bool first = true;
1246 while (this_sibling != last_sibling) {
1247 if ((*this_sibling).OID == thisoid) {
1248 if (!first && next_siblings.empty()) {
1249 previous_sibling = (*(this_sibling-1)).OID;
1250 int section_has_children = (*(this_sibling-1)).metadata["haschildren"].values[0].getint();
1251 // if previous sibling has children we need to recurse
1252 // down to the last descendant
1253 while (section_has_children) {
1254 get_children (previous_sibling, args["c"], args["l"], metadata, false,
1255 collectproto, presponse, logout);
1256 if (!presponse.docInfo.empty()) {
1257 ResultDocInfo_tarray::iterator it = presponse.docInfo.end() - 1;
1258 previous_sibling = (*it).OID;
1259 section_has_children = (*it).metadata["haschildren"].values[0].getint();
1260 } else {
1261 section_has_children = 0; // this should never happen
1262 }
1263 }
1264 }
1265
1266 if ((this_sibling+1) != last_sibling) {
1267 next_siblings.push_back((*(this_sibling+1)).OID);
1268 } else {
1269 next_siblings.push_back("");
1270 }
1271 break;
1272 }
1273 ++this_sibling;
1274 first = false;
1275 }
1276 thisoid = get_parent(thisoid);
1277 --parentcount;
1278 }
1279
1280 // work out values for next link
1281 if (haschildren) {
1282#ifndef DOCHANLE
1283 disp.setmacro ("httpnextarrow", "document", "_httpdocument_&amp;cl=" + args["cl"] +
1284 "&amp;d=" + arg_d + ".fc");
1285#else
1286 disp.setmacro ("httpnextarrow", "document", "_httpdocumenthandle_("+args["c"]+","+arg_d + ".fc)";
1287
1288#endif
1289
1290 } else {
1291 text_tarray::const_iterator h = next_siblings.begin();
1292 text_tarray::const_iterator e = next_siblings.end();
1293 while (h != e) {
1294 if (!(*h).empty()) {
1295#ifndef DOCHANLE
1296 disp.setmacro ("httpnextarrow", "document", "_httpdocument_&amp;cl=" + args["cl"] +
1297 "&amp;d=" + *h);
1298#else
1299 disp.setmacro ("httpnextarrow", "document", "_httpdocumenthandle_("+args["c"]+","+*h+")";
1300
1301#endif
1302
1303 break;
1304 }
1305 ++h;
1306 }
1307 }
1308
1309 // work out value for previous link
1310 if (!previous_sibling.empty()) {
1311#ifndef DOCHANDLE
1312 disp.setmacro ("httpprevarrow", "document", "_httpdocument_&amp;cl=" + args["cl"] +
1313 "&amp;d=" + previous_sibling);
1314#else
1315 disp.setmacro ("httpprevarrow", "document", "_httpdocumenthandle_("+args["c"]+","+ previous_sibling+")");
1316
1317#endif
1318
1319 } else {
1320 if (countchar(arg_d.begin(), arg_d.end(), '.')) {
1321#ifndef DOCHANDLE
1322 disp.setmacro ("httpprevarrow", "document", "_httpdocument_&amp;cl=" + args["cl"] +
1323 "&amp;d=" + get_parent(arg_d));
1324#else
1325 disp.setmacro ("httpprevarrow", "document", "_httpdocumenthandle_("+args["c"]+","+get_parent(arg_d)+")");
1326
1327#endif
1328
1329 }
1330 }
1331}
Note: See TracBrowser for help on using the repository browser.