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

Last change on this file since 649 was 649, checked in by sjboddie, 25 years ago
  • metadata now returns mp rather than array
  • redesigned browsing support (although it's not finished so

won't currently work ;-)

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