source: trunk/gsdl/src/recpt/queryaction.cpp@ 634

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

fixed up the query selection boxes to display properly if there's only
a single index/sub-collection

  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 21.4 KB
Line 
1/**********************************************************************
2 *
3 * queryaction.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: queryaction.cpp 634 1999-09-24 04:49:39Z sjboddie $
25 *
26 *********************************************************************/
27
28/*
29 $Log$
30 Revision 1.25 1999/09/24 04:49:39 sjboddie
31 fixed up the query selection boxes to display properly if there's only
32 a single index/sub-collection
33
34 Revision 1.24 1999/09/22 03:44:31 sjboddie
35 EndResults query filter option may now take '-1' for 'all'
36
37 Revision 1.23 1999/09/21 11:34:42 sjboddie
38 added Maxdocs queryfilter option which may be -1 for 'all'
39
40 Revision 1.22 1999/09/07 23:08:51 rjmcnab
41 removed some compiler warnings
42
43 Revision 1.21 1999/09/07 04:56:57 sjboddie
44 added GPL notice
45
46 Revision 1.20 1999/08/25 04:47:55 sjboddie
47 added advanced search option - other minor changes
48
49 Revision 1.19 1999/08/13 04:17:24 sjboddie
50 small change to do with new collection-level metadata
51
52 Revision 1.18 1999/08/10 22:46:33 sjboddie
53 changed format option result to QueryResults and added QueryLinks option
54
55 Revision 1.17 1999/07/30 02:24:42 sjboddie
56 added collectinfo argument to some functions
57
58 Revision 1.16 1999/07/19 00:16:58 sjboddie
59 no longer display documents that don't match all phrases in query string
60
61 Revision 1.15 1999/07/16 08:33:36 rjmcnab
62 Changed the logic for getting the results string slightly
63
64 Revision 1.14 1999/07/16 03:41:29 sjboddie
65 changed isApprox
66
67 Revision 1.13 1999/07/16 00:19:01 sjboddie
68 some changes to the way quoted queries are handled
69
70 Revision 1.12 1999/07/09 02:17:55 rjmcnab
71 Setting macros needed for a second query.
72
73 Revision 1.11 1999/07/07 06:13:10 rjmcnab
74 Added ability to combine two independant queries.
75
76 Revision 1.10 1999/07/07 05:49:35 sjboddie
77 had another crack at the format string code - created a new formattools
78 module. It can now handle {If} and {Or} statements although there's a
79 bug preventing nested if's and or's.
80
81 Revision 1.9 1999/07/01 22:48:46 sjboddie
82 had a go at getting a query result format string working
83
84 Revision 1.8 1999/06/27 22:02:11 sjboddie
85 author is added to queryresults if there is one
86
87 Revision 1.7 1999/06/26 01:10:18 rjmcnab
88 Made h, i, and n arguments saved in the compressed arguments.
89
90 Revision 1.6 1999/06/24 05:12:25 sjboddie
91 lots of small changes
92
93 Revision 1.5 1999/06/16 04:03:48 sjboddie
94 Now sets "cl" arg to "search" when going to a document from a search
95 results page. This allows the close book icon (in hierarchy toc) to
96 take you back to the results page if that's where you came from.
97 If you got to the document page somehow other than from a
98 classification or a search (i.e. if "cl" isn't set) then the close
99 book icon is disabled
100
101 Revision 1.4 1999/06/16 02:08:38 sjboddie
102 got queryaction working
103
104 Revision 1.3 1999/03/25 03:06:45 sjboddie
105
106 altered receptionist slightly so it now passes *collectproto to
107 define_internal_macros and define_external_macros - need it
108 for browseaction
109
110 Revision 1.2 1999/03/03 20:26:50 rjmcnab
111
112 Modified stuff.
113
114 Revision 1.1 1999/02/28 22:45:21 rjmcnab
115
116 Initial revision.
117
118 */
119
120
121#include "queryaction.h"
122#include "querytools.h"
123#include "formattools.h"
124
125queryaction::queryaction () {
126
127 num_phrases = 0;
128
129 // this action uses cgi variable "a"
130 cgiarginfo arg_ainfo;
131 arg_ainfo.shortname = "a";
132 arg_ainfo.longname = "action";
133 arg_ainfo.multiplechar = true;
134 arg_ainfo.defaultstatus = cgiarginfo::weak;
135 arg_ainfo.argdefault = "q";
136 arg_ainfo.savedarginfo = cgiarginfo::must;
137 argsinfo.addarginfo (NULL, arg_ainfo);
138
139 // "b" - 0 = simple, 1 = advanced
140 arg_ainfo.shortname = "b";
141 arg_ainfo.longname = "query mode";
142 arg_ainfo.multiplechar = false;
143 arg_ainfo.defaultstatus = cgiarginfo::weak;
144 arg_ainfo.argdefault = "0";
145 arg_ainfo.savedarginfo = cgiarginfo::must;
146 argsinfo.addarginfo (NULL, arg_ainfo);
147
148 // "h"
149 arg_ainfo.shortname = "h";
150 arg_ainfo.longname = "main index";
151 arg_ainfo.multiplechar = true;
152 arg_ainfo.defaultstatus = cgiarginfo::weak;
153 arg_ainfo.argdefault = "";
154 arg_ainfo.savedarginfo = cgiarginfo::must;
155 argsinfo.addarginfo (NULL, arg_ainfo);
156
157 // "h2"
158 arg_ainfo.shortname = "h2";
159 arg_ainfo.longname = "main index for second query";
160 arg_ainfo.multiplechar = true;
161 arg_ainfo.defaultstatus = cgiarginfo::weak;
162 arg_ainfo.argdefault = "";
163 arg_ainfo.savedarginfo = cgiarginfo::must;
164 argsinfo.addarginfo (NULL, arg_ainfo);
165
166 // "j"
167 arg_ainfo.shortname = "j";
168 arg_ainfo.longname = "sub collection index";
169 arg_ainfo.multiplechar = true;
170 arg_ainfo.defaultstatus = cgiarginfo::weak;
171 arg_ainfo.argdefault = "";
172 arg_ainfo.savedarginfo = cgiarginfo::must;
173 argsinfo.addarginfo (NULL, arg_ainfo);
174
175 // "j2"
176 arg_ainfo.shortname = "j2";
177 arg_ainfo.longname = "sub collection index for second query";
178 arg_ainfo.multiplechar = true;
179 arg_ainfo.defaultstatus = cgiarginfo::weak;
180 arg_ainfo.argdefault = "";
181 arg_ainfo.savedarginfo = cgiarginfo::must;
182 argsinfo.addarginfo (NULL, arg_ainfo);
183
184 // "n"
185 arg_ainfo.shortname = "n";
186 arg_ainfo.longname = "language index";
187 arg_ainfo.multiplechar = true;
188 arg_ainfo.defaultstatus = cgiarginfo::weak;
189 arg_ainfo.argdefault = "";
190 arg_ainfo.savedarginfo = cgiarginfo::must;
191 argsinfo.addarginfo (NULL, arg_ainfo);
192
193 // "n2"
194 arg_ainfo.shortname = "n2";
195 arg_ainfo.longname = "language index for second query";
196 arg_ainfo.multiplechar = true;
197 arg_ainfo.defaultstatus = cgiarginfo::weak;
198 arg_ainfo.argdefault = "";
199 arg_ainfo.savedarginfo = cgiarginfo::must;
200 argsinfo.addarginfo (NULL, arg_ainfo);
201
202 // "q"
203 arg_ainfo.shortname = "q";
204 arg_ainfo.longname = "query string";
205 arg_ainfo.multiplechar = true;
206 arg_ainfo.defaultstatus = cgiarginfo::weak;
207 arg_ainfo.argdefault = "";
208 arg_ainfo.savedarginfo = cgiarginfo::must;
209 argsinfo.addarginfo (NULL, arg_ainfo);
210
211 // "q2"
212 arg_ainfo.shortname = "q2";
213 arg_ainfo.longname = "query string for second query";
214 arg_ainfo.multiplechar = true;
215 arg_ainfo.defaultstatus = cgiarginfo::weak;
216 arg_ainfo.argdefault = "";
217 arg_ainfo.savedarginfo = cgiarginfo::must;
218 argsinfo.addarginfo (NULL, arg_ainfo);
219
220 // "cq2" ""=don't combine, "and", "or", "not"
221 arg_ainfo.shortname = "cq2";
222 arg_ainfo.longname = "combine queries";
223 arg_ainfo.multiplechar = true;
224 arg_ainfo.defaultstatus = cgiarginfo::weak;
225 arg_ainfo.argdefault = "";
226 arg_ainfo.savedarginfo = cgiarginfo::must;
227 argsinfo.addarginfo (NULL, arg_ainfo);
228
229 // "t" - 1 = ranked 0 = boolean
230 arg_ainfo.shortname = "t";
231 arg_ainfo.longname = "search type";
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 // "k"
239 arg_ainfo.shortname = "k";
240 arg_ainfo.longname = "casefolding";
241 arg_ainfo.multiplechar = false;
242 arg_ainfo.defaultstatus = cgiarginfo::weak;
243 arg_ainfo.argdefault = "1";
244 arg_ainfo.savedarginfo = cgiarginfo::must;
245 argsinfo.addarginfo (NULL, arg_ainfo);
246
247 // "s"
248 arg_ainfo.shortname = "s";
249 arg_ainfo.longname = "stemming";
250 arg_ainfo.multiplechar = false;
251 arg_ainfo.defaultstatus = cgiarginfo::weak;
252 arg_ainfo.argdefault ="0";
253 arg_ainfo.savedarginfo = cgiarginfo::must;
254 argsinfo.addarginfo (NULL, arg_ainfo);
255
256 // "m"
257 arg_ainfo.shortname = "m";
258 arg_ainfo.longname = "maximum number of documents";
259 arg_ainfo.multiplechar = true;
260 arg_ainfo.defaultstatus = cgiarginfo::weak;
261 arg_ainfo.argdefault = "50";
262 arg_ainfo.savedarginfo = cgiarginfo::must;
263 argsinfo.addarginfo (NULL, arg_ainfo);
264
265 // "o"
266 arg_ainfo.shortname = "o";
267 arg_ainfo.longname = "hits per page";
268 arg_ainfo.multiplechar = true;
269 arg_ainfo.defaultstatus = cgiarginfo::weak;
270 arg_ainfo.argdefault = "20";
271 arg_ainfo.savedarginfo = cgiarginfo::must;
272 argsinfo.addarginfo (NULL, arg_ainfo);
273
274 // "r"
275 arg_ainfo.shortname = "r";
276 arg_ainfo.longname = "start results from";
277 arg_ainfo.multiplechar = true;
278 arg_ainfo.defaultstatus = cgiarginfo::weak;
279 arg_ainfo.argdefault = "1";
280 arg_ainfo.savedarginfo = cgiarginfo::must;
281 argsinfo.addarginfo (NULL, arg_ainfo);
282}
283
284void queryaction::configure (const text_t &key, const text_tarray &cfgline) {
285 action::configure (key, cfgline);
286}
287
288bool queryaction::init (ostream &logout) {
289 return action::init (logout);
290}
291
292bool queryaction::check_cgiargs (cgiargsinfoclass &argsinfo, cgiargsclass &args,
293 ostream &logout) {
294
295 // check t argument
296 int arg_t = args.getintarg("t");
297 if (arg_t != 0 && arg_t != 1) {
298 logout << "Warning: \"t\" argument out of range (" << arg_t << ")\n";
299 cgiarginfo *tinfo = argsinfo.getarginfo ("t");
300 if (tinfo != NULL) args["t"] = tinfo->argdefault;
301 }
302
303 // check k argument
304 int arg_k = args.getintarg("k");
305 if (arg_k != 0 && arg_k != 1) {
306 logout << "Warning: \"k\" argument out of range (" << arg_k << ")\n";
307 cgiarginfo *kinfo = argsinfo.getarginfo ("k");
308 if (kinfo != NULL) args["k"] = kinfo->argdefault;
309 }
310
311 // check s argument
312 int arg_s = args.getintarg("s");
313 if (arg_s != 0 && arg_s != 1) {
314 logout << "Warning: \"s\" argument out of range (" << arg_s << ")\n";
315 cgiarginfo *sinfo = argsinfo.getarginfo ("s");
316 if (sinfo != NULL) args["s"] = sinfo->argdefault;
317 }
318
319 // check m argument
320 int arg_m = args.getintarg("m");
321 if (arg_m < -1) {
322 logout << "Warning: \"m\" argument less than -1 (" << arg_m << ")\n";
323 cgiarginfo *minfo = argsinfo.getarginfo ("m");
324 if (minfo != NULL) args["m"] = minfo->argdefault;
325 }
326
327 // check o argument
328 int arg_o = args.getintarg("o");
329 if (arg_o < -1) {
330 logout << "Warning: \"o\" argument less than -1 (" << arg_o << ")\n";
331 cgiarginfo *oinfo = argsinfo.getarginfo ("o");
332 if (oinfo != NULL) args["o"] = oinfo->argdefault;
333 }
334
335 // check r argument
336 int arg_r = args.getintarg("r");
337 if (arg_r < 1) {
338 logout << "Warning: \"r\" argument less than 1 (" << arg_r << ")\n";
339 cgiarginfo *rinfo = argsinfo.getarginfo ("r");
340 if (rinfo != NULL) args["r"] = rinfo->argdefault;
341 }
342
343 return true;
344}
345
346void queryaction::get_cgihead_info (cgiargsclass &/*args*/, response_t &response,
347 text_t &response_data, ostream &/*logout*/) {
348 response = content;
349 response_data = "text/html";
350}
351
352void queryaction::define_internal_macros (const ColInfoResponse_t &/*collectinfo*/, displayclass &disp,
353 cgiargsclass &args, recptproto * /*collectproto*/,
354 ostream &/*logout*/) {
355
356 // define_internal_macros sets the following macros:
357
358 // _quotedquery_ the part of the query string that was quoted for post-processing
359
360
361
362 // The following macros are set later (in define_query_macros) as they can't be set until
363 // the query has been done.
364
365 // _freqmsg_ the term frequency string
366
367 // _resultline_ the "x documents matched the query" string
368
369 // _prevfirst_ these are used when setting up the links to previous/next
370 // _prevlast_ pages of results (_thisfirst_ and _thislast_ are used to set
371 // _nextfirst_ the 'results x-x for query: xxxx' string in the title bar)
372 // _nextlast_
373 // _thisfirst_
374 // _thislast_
375
376
377 // get the quoted bits of the query string and set _quotedquery_
378 text_tarray phrases;
379 get_phrases (args["q"], phrases);
380 text_tarray::const_iterator phere = phrases.begin();
381 text_tarray::const_iterator pend = phrases.end();
382 bool first = true;
383 text_t quotedquery;
384 while (phere != pend) {
385 if (!first)
386 if ((phere +1) == pend) quotedquery += " and ";
387 else quotedquery += ", ";
388
389 quotedquery += "\"" + *phere + "\"";
390 first = false;
391 phere ++;
392 }
393 if (args.getintarg("s")) quotedquery += "_textstemon_";
394 disp.setmacro ("quotedquery", "query", quotedquery);
395
396 // we'll also set num_phrases here so we don't have to parse the
397 // querystring again later (we need to know this before outputting
398 // results so we don't include results for documents not containing
399 // all requested phrases).
400 num_phrases = phrases.size();
401
402}
403
404// sets the selection box macros _hselection_, _jselection_, and _nselection_.
405void queryaction::set_option_macro (const text_t &macroname, text_t current_value,
406 const FilterOption_t &option, displayclass &disp) {
407
408 if (option.validValues.empty()) return;
409 else if (option.validValues.size() == 1) {
410 disp.setmacro (macroname + "selection", "Global", "_" + option.defaultValue + "_");
411 return;
412 }
413 if (option.validValues.size() < 2) return;
414
415 text_t macrovalue = "<select name=\"" + macroname + "\">\n";
416
417 if (current_value.empty()) current_value = option.defaultValue;
418
419 text_tarray::const_iterator thisvalue = option.validValues.begin();
420 text_tarray::const_iterator endvalue = option.validValues.end();
421
422 while (thisvalue != endvalue) {
423 macrovalue += "<option value=\"" + *thisvalue + "\"";
424 if (*thisvalue == current_value)
425 macrovalue += " selected";
426 macrovalue += ">_" + *thisvalue + "_\n";
427 thisvalue ++;
428 }
429 macrovalue += "</select>\n";
430 disp.setmacro (macroname + "selection", "Global", macrovalue);
431}
432
433void queryaction::define_external_macros (const ColInfoResponse_t &/*collectinfo*/, displayclass &disp,
434 cgiargsclass &args, recptproto *collectproto,
435 ostream &logout) {
436
437 // define_external_macros sets the following macros:
438
439 // some or all of these may not be required to be set
440 // _hselection_, _h2selection_ the selection box for the main part of the index
441 // _jselection_, _j2selection_ the selection box for the subcollection part of the index
442 // _nselection_, _n2selection_ the selection box for the language part of the index
443 // _cq2selection the selection box for combining two queries
444
445
446 // can't do anything if collectproto is null (i.e. no collection was specified)
447 if (collectproto == NULL) return;
448
449 comerror_t err;
450 InfoFilterOptionsResponse_t response;
451 InfoFilterOptionsRequest_t request;
452 request.filterName = "QueryFilter";
453
454 collectproto->get_filteroptions (args["c"], request, response, err, logout);
455 if (err == noError) {
456
457 FilterOption_tmap::const_iterator it;
458 FilterOption_tmap::const_iterator end = response.filterOptions.end();
459
460 // _hselection_ and _h2selection_ (Index)
461 it = response.filterOptions.find ("Index");
462 if (it != end) set_option_macro ("h", args["h"], (*it).second, disp);
463 if (it != end) set_option_macro ("h2", args["h2"], (*it).second, disp);
464
465 // _jselection_ and _j2selection_ (Subcollection)
466 it = response.filterOptions.find ("Subcollection");
467 if (it != end) set_option_macro ("j", args["j"], (*it).second, disp);
468 if (it != end) set_option_macro ("j2", args["j2"], (*it).second, disp);
469
470 // _nselection_ and _n2selection_ (Language)
471 it = response.filterOptions.find ("Language");
472 if (it != end) set_option_macro ("n", args["n"], (*it).second, disp);
473 if (it != end) set_option_macro ("n2", args["n2"], (*it).second, disp);
474
475 // _cq2selection_ (CombineQuery)
476 it = response.filterOptions.find ("CombineQuery");
477 if (it != end) set_option_macro ("cq2", args["cq2"], (*it).second, disp);
478 }
479}
480
481bool queryaction::do_action (cgiargsclass &args, const ColInfoResponse_t &collectinfo,
482 recptproto *collectproto, displayclass &disp,
483 outconvertclass &outconvert, ostream &textout,
484 ostream &logout) {
485
486 if (formatstring.empty()) {
487 text_tmap::const_iterator result = collectinfo.format.find("QueryResults");
488 if (result != collectinfo.format.end())
489 formatstring = (*result).second;
490 }
491
492 // see if there's a QueryLinks format option
493 text_t querylinkmeta;
494 bool havequerylink = false;
495 text_tmap::const_iterator it = collectinfo.format.find("QueryLinks");
496 if (it != collectinfo.format.end()) {
497 querylinkmeta = (*it).second;
498 havequerylink = true;
499 }
500
501 // if we still don't have a format string use the default
502 if (formatstring.empty())
503 formatstring = "<td valign=top nowrap>[link]_icontext_[/link]</td><td>[Title]</td>";
504
505 if (collectproto == NULL) {
506 logout << "queryaction::do_action called with NULL collectproto\n";
507 textout << outconvert << disp << "_query:header_\n"
508 << "Error: Attempt to do query without setting collection\n"
509 << "_query:footer_\n";
510 } else {
511
512 FilterRequest_t request;
513 FilterResponse_t response;
514 format_t *formatlistptr = new format_t();
515
516 parse_formatstring (formatstring, formatlistptr, request.fields, request.getParents);
517
518 if (havequerylink)
519 request.fields.push_back (querylinkmeta);
520
521 int metasize = request.fields.size();
522
523 // do the query
524 request.filterResultOptions = FROID | FRmetadata | FRtermFreq;
525 if (!do_query (request, args, collectproto, response, logout))
526 return false;
527
528 // set macros
529 define_query_macros (args, disp, response);
530
531 // output the header
532 textout << outconvert << disp << "_query:header_\n"
533 << "_query:content_";
534
535 // output the results
536 textout << "<table cellspacing=4>\n";
537 ResultDocInfo_tarray::const_iterator this_doc = response.docInfo.begin();
538 ResultDocInfo_tarray::const_iterator end_doc = response.docInfo.end();
539
540 while (this_doc != end_doc) {
541 // don't include docs that didn't match phrases (if there were any)
542 // those that did match will have been sorted to the top
543 if ((*this_doc).num_phrase_match < num_phrases) break;
544 textout << "<tr>\n";
545 if (havequerylink) {
546 const text_t &qlmeta = (*this_doc).metadata[metasize-1].values.back();
547 if (qlmeta.empty())
548 textout << outconvert << disp
549 << get_formatted_string (*this_doc, formatlistptr, "", "_iconblanktext_") << "\n";
550 else
551 textout << outconvert << disp
552 << get_formatted_string (*this_doc, formatlistptr) << "\n";
553 } else {
554 textout << outconvert << disp
555 << get_formatted_string (*this_doc, formatlistptr) << "\n";
556 }
557 textout << "</tr>\n";
558
559 this_doc ++;
560 }
561 textout << "</table>\n";
562
563 delete (formatlistptr);
564
565 // output the footer
566 textout << outconvert << disp << "_query:footer_";
567 }
568
569 return true;
570}
571
572// define_query_macros sets the macros that couldn't be set until the
573// query had been done. Those macros are _freqmsg_, _quotedquery_,
574// _resultline_, _nextfirst_, _nextlast_, _prevfirst_, _prevlast_,
575// _thisfirst_, and _thislast_
576void queryaction::define_query_macros (cgiargsclass &args, displayclass &disp,
577 const FilterResponse_t &response) {
578 // set up _freqmsg_ and _quotedquery_ macros
579 text_t freqmsg = "_textfreqmsg1_";
580 TermInfo_tarray::const_iterator this_term = response.termInfo.begin();
581 TermInfo_tarray::const_iterator end_term = response.termInfo.end();
582 while (this_term != end_term) {
583 freqmsg += (*this_term).term + ": " + (*this_term).freq;
584 if ((this_term + 1) != end_term)
585 freqmsg += ", ";
586 this_term ++;
587 }
588
589 disp.setmacro ("freqmsg", "query", freqmsg);
590
591
592 // set up _resultline_ macro
593 text_t resline;
594 int maxdocs = args.getintarg("m");
595 int numdocs = response.numDocs;
596 if (maxdocs == -1) maxdocs = response.numDocs;
597 isapprox isApprox = response.isApprox;
598
599 // if there were phrases (post-processing) we're not going to include
600 // those documents that didn't match
601 if (num_phrases > 0) {
602 numdocs = 0;
603 isApprox = Exact;
604 ResultDocInfo_tarray::const_iterator this_doc = response.docInfo.begin();
605 ResultDocInfo_tarray::const_iterator end_doc = response.docInfo.end();
606 while (this_doc != end_doc) {
607 if ((*this_doc).num_phrase_match == num_phrases) numdocs ++;
608 else break; // we can bail here as matching docs are sorted to top
609 this_doc++;
610 }
611 }
612
613 if (isApprox == Approximate) resline = "_textapprox_";
614 else if (isApprox == MoreThan) resline = "_textmorethan_";
615
616 if (numdocs == 0) resline = "_textnodocs_";
617 else if (numdocs == 1) resline += "_text1doc_";
618 else resline += text_t(numdocs) + " _textlotsdocs_";
619
620 disp.setmacro("resultline", "query", resline);
621
622 int firstdoc = args.getintarg("r");
623 int hitsperpage = args.getintarg("o");
624 if (hitsperpage == -1) hitsperpage = numdocs;
625
626 // set up _thisfirst_ and _thislast_ macros
627 disp.setmacro ("thisfirst", "query", firstdoc);
628 int thislast = firstdoc + (hitsperpage - 1);
629 if (thislast > numdocs) thislast = numdocs;
630 disp.setmacro ("thislast", "query", thislast);
631
632 // set up _prevfirst_ and _prevlast_ macros
633 if (firstdoc > 1) {
634 disp.setmacro ("prevlast", "query", firstdoc - 1);
635 int prevfirst = firstdoc - hitsperpage;
636 if (prevfirst < 1) prevfirst = 1;
637 disp.setmacro ("prevfirst", "query", prevfirst);
638 }
639
640 // set up _nextfirst_ and _nextlast_ macros
641 if (thislast < numdocs) {
642 disp.setmacro ("nextfirst", "query", thislast + 1);
643 int nextlast = thislast + hitsperpage;
644 if (nextlast > numdocs) nextlast = numdocs;
645 disp.setmacro ("nextlast", "query", nextlast);
646 }
647}
648
649
650
Note: See TracBrowser for help on using the repository browser.