Index: trunk/gsdl/src/recpt/queryaction.cpp
===================================================================
--- trunk/gsdl/src/recpt/queryaction.cpp	(revision 756)
+++ trunk/gsdl/src/recpt/queryaction.cpp	(revision 757)
@@ -28,4 +28,8 @@
 /*
    $Log$
+   Revision 1.27  1999/11/01 21:53:27  sjboddie
+   added cross-collection searching capability - still needs lots of
+   work but the basic functionality is there
+
    Revision 1.26  1999/10/10 08:14:10  sjboddie
    - metadata now returns mp rather than array
@@ -127,4 +131,15 @@
 #include "querytools.h"
 #include "formattools.h"
+#include "cgiutils.h"
+
+void colinfo_t::clear () {
+  formatlistptr = NULL;
+  browserptr = NULL;
+}
+
+void QueryResult_t::clear() {
+  doc.clear();
+  collection.clear();
+}
 
 queryaction::queryaction () {
@@ -285,4 +300,32 @@
   arg_ainfo.savedarginfo = cgiarginfo::must;
   argsinfo.addarginfo (NULL, arg_ainfo);
+
+  // "ccs"
+  arg_ainfo.shortname = "ccs";
+  arg_ainfo.longname = "cross collection searching";
+  arg_ainfo.multiplechar = false;
+  arg_ainfo.defaultstatus = cgiarginfo::weak;
+  arg_ainfo.argdefault = "0";
+  arg_ainfo.savedarginfo = cgiarginfo::must;
+  argsinfo.addarginfo (NULL, arg_ainfo);
+
+  // "ccp"
+  arg_ainfo.shortname = "ccp";
+  arg_ainfo.longname = "cross collection page";
+  arg_ainfo.multiplechar = false;
+  arg_ainfo.defaultstatus = cgiarginfo::weak;
+  arg_ainfo.argdefault = "0";
+  arg_ainfo.savedarginfo = cgiarginfo::must;
+  argsinfo.addarginfo (NULL, arg_ainfo);
+
+  // "cc"
+  arg_ainfo.shortname = "cc";
+  arg_ainfo.longname = "collections to search";
+  arg_ainfo.multiplechar = true;
+  arg_ainfo.defaultstatus = cgiarginfo::weak;
+  arg_ainfo.argdefault = "";
+  arg_ainfo.savedarginfo = cgiarginfo::must;
+  argsinfo.addarginfo (NULL, arg_ainfo);
+
 }
 
@@ -349,12 +392,13 @@
 }
 
-void queryaction::get_cgihead_info (cgiargsclass &/*args*/, response_t &response,
-				     text_t &response_data, ostream &/*logout*/) {
+void queryaction::get_cgihead_info (cgiargsclass &/*args*/, recptprotolistclass * /*protos*/,
+				    response_t &response, text_t &response_data, 
+				    ostream &/*logout*/) {
   response = content;
   response_data = "text/html";
 }
 
-void queryaction::define_internal_macros (const ColInfoResponse_t &/*collectinfo*/, displayclass &disp, 
-					  cgiargsclass &args, recptproto * /*collectproto*/, 
+void queryaction::define_internal_macros (displayclass &disp, cgiargsclass &args, 
+					  recptprotolistclass * /*protos*/, 
 					  ostream &/*logout*/) {
 
@@ -398,11 +442,4 @@
   if (args.getintarg("s")) quotedquery += "_textstemon_";
   disp.setmacro ("quotedquery", "query", quotedquery);
-
-  // we'll also set num_phrases here so we don't have to parse the 
-  // querystring again later (we need to know this before outputting 
-  // results so we don't include results for documents not containing 
-  // all requested phrases).
-  num_phrases = phrases.size();
-
 }
 
@@ -436,7 +473,6 @@
 }
 
-void queryaction::define_external_macros (const ColInfoResponse_t &/*collectinfo*/, displayclass &disp, 
-					  cgiargsclass &args, recptproto *collectproto, 
-					  ostream &logout) {
+void queryaction::define_external_macros (displayclass &disp, cgiargsclass &args, 
+					  recptprotolistclass *protos, ostream &logout) {
 
   // define_external_macros sets the following macros:
@@ -450,4 +486,5 @@
   
   // can't do anything if collectproto is null (i.e. no collection was specified)
+  recptproto *collectproto = protos->getrecptproto (args["c"], logout);
   if (collectproto == NULL) return;
 
@@ -484,89 +521,402 @@
 }
 
-bool queryaction::do_action (cgiargsclass &args, const ColInfoResponse_t &collectinfo, 
-			     recptproto *collectproto, displayclass &disp, 
+void queryaction::output_ccp (cgiargsclass &args, recptprotolistclass *protos,
+			      displayclass &disp, outconvertclass &outconvert,
+			      ostream &textout, ostream &logout) {
+
+  ColInfoResponse_t cinfo;
+  comerror_t err;
+  InfoFilterOptionsResponse_t fresponse;
+  InfoFilterOptionsRequest_t frequest;
+  frequest.filterName = "QueryFilter";
+
+  text_t &index = args["h"];
+  text_t &subcollection = args["j"];
+  text_t &language = args["n"];
+
+  textout << outconvert << disp << "_query:header_\n"
+	  << "<center>_navigationbar_</center><br>\n"
+	  << "<form name=QueryForm method=get action=\"_gwcgi_\">\n"
+	  << "<input type=hidden name=a value=\"q\">\n"
+	  << "<input type=hidden name=e value=\"_compressedoptions_\">\n"
+	  << "<input type=hidden name=ccp value=\"1\">\n"
+	  << "<center><table width=_pagewidth_><tr valign=top>\n"
+	  << "<td>Select collections to search for \"" << args["q"] 
+	  << "\" <i>(index=" << index << " subcollection=" << subcollection
+	  << " language=" << language << ")</i></td>\n"
+	  << "<td><input type=\"submit\" value=\"_query:textbeginsearch_\"></td>\n"
+	  << "</tr></table></center>\n"
+	  << "<center><table width=_pagewidth_>\n";
+
+  
+  recptprotolistclass::iterator rprotolist_here = protos->begin();
+  recptprotolistclass::iterator rprotolist_end = protos->end();
+  while (rprotolist_here != rprotolist_end) {
+    if ((*rprotolist_here).p != NULL) {
+      
+      text_tarray collist;
+      (*rprotolist_here).p->get_collection_list (collist, err, logout);
+      if (err == noError) {
+	text_tarray::iterator collist_here = collist.begin();
+	text_tarray::iterator collist_end = collist.end();
+	while (collist_here != collist_end) {
+	  
+	  (*rprotolist_here).p->get_collectinfo (*collist_here, cinfo, err, logout);
+	  //	  if (err == noError && cinfo.isPublic && (cinfo.buildDate > 0)) {
+	  if (err == noError && (cinfo.buildDate > 0)) {
+	    
+	    (*rprotolist_here).p->get_filteroptions (*collist_here, frequest, fresponse, err, logout);
+	    if (err == noError) {
+	      
+	      FilterOption_tmap::const_iterator it;
+	      FilterOption_tmap::const_iterator end = fresponse.filterOptions.end();
+	      if (!index.empty()) {
+		it = fresponse.filterOptions.find ("Index");
+		if (it == end) {collist_here ++; continue;}
+		text_tarray::const_iterator there = (*it).second.validValues.begin();
+		text_tarray::const_iterator tend = (*it).second.validValues.end();
+		while (there != tend) {
+		  if (*there == index) break;
+		  there ++;
+		}
+		if (there == tend) {collist_here++; continue;}
+	      }
+	      if (!subcollection.empty()) {
+		it = fresponse.filterOptions.find ("Subcollection");
+		if (it == end) {collist_here++; continue;}
+		text_tarray::const_iterator there = (*it).second.validValues.begin();
+		text_tarray::const_iterator tend = (*it).second.validValues.end();
+		while (there != tend) {
+		  if (*there == subcollection) break;
+		  there ++;
+		}
+		if (there == tend) {collist_here++; continue;}
+	      }
+	      if (!language.empty()) {
+		it = fresponse.filterOptions.find ("Language");
+		if (it == end) {collist_here++; continue;}
+		text_tarray::const_iterator there = (*it).second.validValues.begin();
+		text_tarray::const_iterator tend = (*it).second.validValues.end();
+		while (there != tend) {
+		  if (*there == language) break;
+		  there ++;
+		}
+		if (there == tend) {collist_here++; continue;}
+	      }
+	    
+	      // we've got a matching collection
+	      textout << outconvert 
+		      << "<tr><td><input type=checkbox checked name=cc value=\""
+		      << *collist_here << "\"></td><td>\n";
+	      
+	      if (!cinfo.collectionmeta["collectionname"].empty())
+		textout << outconvert << disp << cinfo.collectionmeta["collectionname"];
+	      else 
+		textout << outconvert << *collist_here;
+	      
+	      textout << "\n</td><td>";
+	      
+	    }
+	    
+	    textout << "\n</td></tr>\n";
+	  }
+	  collist_here ++;
+	}
+      }
+    }
+    rprotolist_here ++;
+  }
+  textout << outconvert << disp 
+	  << "</table></center>\n"
+	  << "</form>\n"
+	  << "_query:footer_\n";
+  
+}
+
+bool queryaction::do_action (cgiargsclass &args, recptprotolistclass *protos, 
+			     browsermapclass *browsers, displayclass &disp, 
 			     outconvertclass &outconvert, ostream &textout, 
 			     ostream &logout) {
-
-  if (formatstring.empty()) {
-    text_tmap::const_iterator result = collectinfo.format.find("QueryResults");
-    if (result != collectinfo.format.end())
-      formatstring = (*result).second;
-  }
-
-  // see if there's a QueryLinks format option
-  text_t querylinkmeta;
-  bool havequerylink = false;
-  text_tmap::const_iterator it = collectinfo.format.find("QueryLinks");
-  if (it != collectinfo.format.end()) {
-    querylinkmeta = (*it).second;
-    havequerylink = true;
-  }
-
-  // if we still don't have a format string use the default
-  if (formatstring.empty()) 
-    formatstring = "<td valign=top nowrap>[link]_icontext_[/link]</td><td>[Title]</td>";
-
+  
+  if (args["ccs"] == 1) {
+    // cross collection searching
+    if (args["ccp"] != 1) {
+      // display the cross collection search page
+      output_ccp (args, protos, disp, outconvert, textout, logout);
+    } else {
+      // query the selected collections
+      if (!search_multiple_collections (args, protos, browsers, disp, outconvert,
+					textout, logout)) return false;
+    }
+  } else {
+    // simply query the current collection
+    if (!search_single_collection (args, protos, browsers, disp, outconvert,
+				   textout, logout)) return false;
+  }
+
+  return true;
+}
+
+bool queryaction::search_multiple_collections (cgiargsclass &args, recptprotolistclass *protos,
+					       browsermapclass *browsers, displayclass &disp,
+					       outconvertclass &outconvert, ostream &textout,
+					       ostream &logout) {
+
+  text_tarray collections;
+  
+  text_t arg_cc = args["cc"];
+  decode_cgi_arg (arg_cc);
+  splitchar (arg_cc.begin(), arg_cc.end(), ',', collections);
+
+  if (collections.empty()) {
+    logout << "queryaction::search_multiple_collections: No collections "
+	   << "set for doing multiple query - will search current collection\n";
+    textout << outconvert << disp << "_query:textwarningnocollections_\n";
+    return search_single_collection (args, protos, browsers, disp, 
+				     outconvert, textout, logout);
+  }
+
+  // queryaction uses "VList" browser to display results,
+  // a queries clasification is "Search"
+  text_t browsertype = "VList";
+  text_t classification = "Search";
+
+  QueryResult_tset results;
+  map<text_t, colinfo_t, lttext_t> colinfomap;
+
+  ColInfoResponse_t cinfo;
+  comerror_t err;
+  FilterRequest_t request;
+  FilterResponse_t response;
+  request.filterResultOptions = FROID | FRmetadata | FRtermFreq | FRranking;
+  text_t formattedstring = args["q"];
+  text_t freqmsg = "_textfreqmsg1_";
+  int numdocs = 0;
+  format_querystring (formattedstring, args.getintarg("b"));
+  set_queryfilter_options (request, formattedstring, args);
+
+  // need to retrieve maxdocs matches for each collection
+  // (will eventually want to tidy this up, do so caching etc.)
+  OptionValue_t option;
+  option.name = "StartResults";
+  option.value = "1";
+  request.filterOptions.push_back (option);
+  
+  option.name = "EndResults";
+  option.value = args["m"];
+  request.filterOptions.push_back (option);
+
+  text_tarray::iterator col_here = collections.begin();
+  text_tarray::iterator col_end = collections.end();
+
+  while (col_here != col_end) {
+
+    request.fields.erase (request.fields.begin(), request.fields.end());
+    request.getParents = false;
+
+    recptproto *collectproto = protos->getrecptproto (*col_here, logout);
+    if (collectproto == NULL) {
+      logout << outconvert << "queryaction::search_multiple_collections: " << *col_here 
+	     << " collection has a NULL collectproto, ignoring\n";
+      col_here ++;
+      continue;
+    }
+    collectproto->get_collectinfo (*col_here, cinfo, err, logout);
+    
+    browserclass *bptr = browsers->getbrowser (browsertype);
+
+    // get the formatstring if there is one 
+    text_t formatstring;
+    if (!get_formatstring (classification, browsertype, 
+			   cinfo.format, formatstring))
+      formatstring = bptr->get_default_formatstring();
+
+    bptr->load_metadata_defaults (request.fields);
+
+    format_t *formatlistptr = new format_t();
+    parse_formatstring (formatstring, formatlistptr, request.fields, request.getParents);
+
+    colinfo_t thiscolinfo;
+    thiscolinfo.formatlistptr = formatlistptr;
+    thiscolinfo.browserptr = bptr;
+    colinfomap[*col_here] = thiscolinfo;
+    
+    // do the query
+    collectproto->filter (*col_here, request, response, err, logout);
+    if (err != noError) {
+      outconvertclass text_t2ascii;
+      logout << text_t2ascii
+	     << "queryaction::search_multiple_collections: call to QueryFilter failed "
+	     << "for " << *col_here << " collection (" << get_comerror_string (err) << ")\n";
+      return false;
+    }
+
+    TermInfo_tarray::const_iterator this_term = response.termInfo.begin();
+    TermInfo_tarray::const_iterator end_term = response.termInfo.end();
+    freqmsg += "<br><b>" + *col_here + "</b>: ";
+    while (this_term != end_term) {
+      freqmsg += (*this_term).term + ": " + (*this_term).freq;
+      if ((this_term + 1) != end_term)
+	freqmsg += ", ";
+      this_term ++;
+    }
+    
+    if (response.numDocs > 0) {
+      numdocs += response.numDocs;
+
+      QueryResult_t thisresult;
+      thisresult.collection = *col_here;
+      ResultDocInfo_tarray::iterator doc_here = response.docInfo.begin();
+      ResultDocInfo_tarray::iterator doc_end = response.docInfo.end();
+      while (doc_here != doc_end) {
+	thisresult.doc = *doc_here;
+	results.insert (thisresult);
+	doc_here ++;
+      }
+    }
+    col_here ++;
+  }
+
+  if (numdocs > 0) disp.setmacro ("freqmsg", "query", freqmsg);
+  else disp.setmacro("resultline", "query", "_textnodocs_");
+
+
+  QueryResult_tset::iterator res_here = results.begin();
+  QueryResult_tset::iterator res_end = results.end();
+  text_tset metadata; // empty !!
+  bool getParents = false; // don't care !!
+  recptproto *collectproto = NULL;
+  bool use_table;
+  ResultDocInfo_t thisdoc;
+  format_t *formatlistptr = NULL;
+  browserclass *browserptr = NULL;
+
+  int maxdocs = args.getintarg("m");
+  int firstdoc = args.getintarg("r");
+  int hitsperpage = args.getintarg("o");
+  if (numdocs > maxdocs) numdocs = maxdocs;
+  if (hitsperpage == -1) hitsperpage = numdocs;
+
+  // set up _thisfirst_ and _thislast_ macros
+  disp.setmacro ("thisfirst", "query", firstdoc);
+  int thislast = firstdoc + (hitsperpage - 1);
+  if (thislast > numdocs) thislast = numdocs;
+  disp.setmacro ("thislast", "query", thislast);
+
+  // set up _prevfirst_ and _prevlast_ macros
+  if (firstdoc > 1) {
+    disp.setmacro ("prevlast", "query", firstdoc - 1);
+    int prevfirst = firstdoc - hitsperpage;
+    if (prevfirst < 1) prevfirst = 1;
+    disp.setmacro ("prevfirst", "query", prevfirst);
+  }
+
+  // set up _nextfirst_ and _nextlast_ macros
+  if (thislast < numdocs) {
+    disp.setmacro ("nextfirst", "query", thislast + 1);
+    int nextlast = thislast + hitsperpage;
+    if (nextlast > numdocs) nextlast = numdocs;
+    disp.setmacro ("nextlast", "query", nextlast);
+  }
+
+  textout << outconvert << disp << "_query:header_\n"
+	  << "_query:content_";
+
+  int count = 1;
+
+  // output results
+  while (res_here != res_end) {
+    if (count < firstdoc) {count ++; res_here ++; continue;}
+    if (count > thislast) break;
+    formatlistptr = colinfomap[(*res_here).collection].formatlistptr;
+    browserptr = colinfomap[(*res_here).collection].browserptr;
+    thisdoc = (*res_here).doc;
+    use_table = is_table_content (formatlistptr);
+    browserptr->output_section_group (thisdoc, args, (*res_here).collection, 0, 
+    				      formatlistptr, use_table, metadata, getParents, 
+    				      collectproto, disp, outconvert, textout, logout);
+    //    textout << outconvert << "(ranking: " << (*res_here).doc.ranking << ")\n";
+    res_here ++;
+    count ++;
+  }
+
+  textout << outconvert << disp << "_query:footer_";
+  
+  // clean up the format_t pointers
+  map<text_t, colinfo_t, lttext_t>::iterator here =  colinfomap.begin();
+  map<text_t, colinfo_t, lttext_t>::iterator end =  colinfomap.end();
+  while (here != end) {
+    delete ((*here).second.formatlistptr);
+    here ++;
+  }
+  return true;
+}
+
+bool queryaction::search_single_collection (cgiargsclass &args, recptprotolistclass *protos,
+					    browsermapclass *browsers, displayclass &disp,
+					    outconvertclass &outconvert, ostream &textout,
+					    ostream &logout) {
+
+  recptproto *collectproto = protos->getrecptproto (args["c"], logout);
   if (collectproto == NULL) {
-    logout << "queryaction::do_action called with NULL collectproto\n";
-    textout << outconvert << disp << "_query:header_\n" 
-	    << "Error: Attempt to do query without setting collection\n"
-	    << "_query:footer_\n";
-  } else {  
-
-    FilterRequest_t request;
-    FilterResponse_t response;
-    format_t *formatlistptr = new format_t();
-
-    parse_formatstring (formatstring, formatlistptr, request.fields, request.getParents);
-
-    if (havequerylink)
-      request.fields.insert (querylinkmeta);
-
-    // do the query
-    request.filterResultOptions = FROID | FRmetadata | FRtermFreq;
-    if (!do_query (request, args, collectproto, response, logout))
-      return false;
+    logout << outconvert << "queryaction::search_single_collection: " << args["c"]
+	   << " collection has a NULL collectproto\n";
+    return false;
+  }
+
+  // queryaction uses "VList" browser to display results,
+  // a queries clasification is "Search"
+  text_t browsertype = "VList";
+  text_t classification = "Search";
+
+  ColInfoResponse_t cinfo;
+  comerror_t err;
+  collectproto->get_collectinfo (args["c"], cinfo, err, logout);
     
-    // set macros 
-    define_query_macros (args, disp, response);
+  browserclass *bptr = browsers->getbrowser (browsertype);
+
+  // get the formatstring if there is one 
+  text_t formatstring;
+  if (!get_formatstring (classification, browsertype, 
+			 cinfo.format, formatstring))
+    formatstring = bptr->get_default_formatstring();
+
+  FilterRequest_t request;
+  FilterResponse_t response;
+  bptr->set_filter_options (request, args);
+  bptr->load_metadata_defaults (request.fields);
+
+  format_t *formatlistptr = new format_t();
+  parse_formatstring (formatstring, formatlistptr, request.fields, request.getParents);
     
-    // output the header
-    textout << outconvert << disp << "_query:header_\n"
-	    << "_query:content_";
-
-    // output the results
-    textout << "<table cellspacing=4>\n";
-    ResultDocInfo_tarray::iterator this_doc = response.docInfo.begin();
-    ResultDocInfo_tarray::iterator end_doc = response.docInfo.end();
-
-    while (this_doc != end_doc) {
-      // don't include docs that didn't match phrases (if there were any)
-      // those that did match will have been sorted to the top
-      if ((*this_doc).num_phrase_match < num_phrases) break;
-      textout << "<tr>\n";
-      if (havequerylink) {
-	const text_t &qlmeta = (*this_doc).metadata[querylinkmeta].values[0];
-	if (qlmeta.empty())
-	  textout << outconvert << disp 
-		  << get_formatted_string (*this_doc, formatlistptr, "", "_iconblanktext_") << "\n";
-	else
-	  textout << outconvert << disp 
-		  << get_formatted_string (*this_doc, formatlistptr) << "\n";
-      } else {
-	textout << outconvert << disp 
-		<< get_formatted_string (*this_doc, formatlistptr) << "\n";
-      }
-      textout << "</tr>\n";
-
-      this_doc ++;
-    }
-    textout << "</table>\n";
-
-    delete (formatlistptr);
-
-    // output the footer
-    textout << outconvert << disp << "_query:footer_";
-  }
+  // do the query
+  request.filterResultOptions = FROID | FRmetadata | FRtermFreq;
+  text_t formattedstring = args["q"];
+  format_querystring (formattedstring, args.getintarg("b"));
+  set_queryfilter_options (request, formattedstring, args);
+  collectproto->filter (args["c"], request, response, err, logout);
+  if (err != noError) {
+    outconvertclass text_t2ascii;
+    logout << text_t2ascii
+	   << "queryaction::search_single_collections: call to QueryFilter failed "
+	   << "for " << args["c"] << " collection (" << get_comerror_string (err) << ")\n";
+    return false;
+  }
+  
+  define_query_macros (args, disp, response);
+
+  textout << outconvert << disp << "_query:header_\n"
+	  << "_query:content_";
+
+  // output the results
+  bool use_table = is_table_content (formatlistptr);
+  bptr->output_section_group (response, args, "", 0, formatlistptr, 
+			      use_table, request.fields, request.getParents, 
+			      collectproto, disp, outconvert, textout, logout);
+  
+
+  textout << outconvert << disp << "_query:footer_";
+  
+  delete (formatlistptr);
   
   return true;
Index: trunk/gsdl/src/recpt/queryaction.h
===================================================================
--- trunk/gsdl/src/recpt/queryaction.h	(revision 756)
+++ trunk/gsdl/src/recpt/queryaction.h	(revision 757)
@@ -33,4 +33,28 @@
 #include "action.h"
 
+struct colinfo_t {
+  void clear();
+  colinfo_t () {clear();}
+
+  format_t *formatlistptr;
+  browserclass *browserptr;
+};
+
+struct QueryResult_t {
+  void clear ();
+  QueryResult_t () {clear();}
+
+  ResultDocInfo_t doc;
+  text_t collection;
+};
+
+struct gteqQueryResult_t 
+{
+  bool operator()(const QueryResult_t &t1, const QueryResult_t &t2) const
+  { return t1.doc.ranking >= t2.doc.ranking; }
+};
+
+typedef set<QueryResult_t, gteqQueryResult_t> QueryResult_tset;
+
 
 class queryaction : public action {
@@ -46,4 +70,19 @@
 			 const FilterOption_t &option, displayclass &disp);
 
+  void output_ccp (cgiargsclass &args, recptprotolistclass *protos,
+		   displayclass &disp, outconvertclass &outconvert,
+		   ostream &textout, ostream &logout);
+  
+
+  bool search_multiple_collections (cgiargsclass &args, recptprotolistclass *protos,
+				    browsermapclass *browsers, displayclass &disp,
+				    outconvertclass &outconvert, ostream &textout,
+				    ostream &logout);
+
+  bool search_single_collection (cgiargsclass &args, recptprotolistclass *protos,
+				 browsermapclass *browsers, displayclass &disp,
+				 outconvertclass &outconvert, ostream &textout,
+				 ostream &logout);
+
 
 public:
@@ -58,18 +97,20 @@
   bool check_cgiargs (cgiargsinfoclass &argsinfo, cgiargsclass &args, 
 		      ostream &logout);
-  void get_cgihead_info (cgiargsclass &args, response_t &response,
-			 text_t &response_data, ostream &logout);
+
+  void get_cgihead_info (cgiargsclass &args, recptprotolistclass *protos,
+			 response_t &response, text_t &response_data, 
+			 ostream &logout);
   
-  void define_internal_macros (const ColInfoResponse_t &collectinfo, displayclass &disp, 
-			       cgiargsclass &args, recptproto *collectproto, ostream &logout);
-  void define_external_macros (const ColInfoResponse_t &collectinfo, displayclass &disp, 
-			       cgiargsclass &args, recptproto *collectproto, ostream &logout);
+  void define_internal_macros (displayclass &disp, cgiargsclass &args, 
+			       recptprotolistclass *protos, ostream &logout);
+
+  void define_external_macros (displayclass &disp, cgiargsclass &args, 
+			       recptprotolistclass *protos, ostream &logout);
   
-  bool do_action (cgiargsclass &args, const ColInfoResponse_t &collectinfo, 
-		  recptproto *collectproto, displayclass &disp, 
+  bool do_action (cgiargsclass &args, recptprotolistclass *protos, 
+		  browsermapclass *browsers, displayclass &disp, 
 		  outconvertclass &outconvert, ostream &textout, 
 		  ostream &logout);
 };
 
-
 #endif
