+ struct hitsbytarget *p;
+ session_enter(se);
+ p = hitsbytarget_nb(se, count, nmem);
+ session_leave(se);
+ return p;
+}
+
+// Compares two hitsbytarget nodes by hitcount
+static int cmp_ht(const void *p1, const void *p2)
+{
+ const struct hitsbytarget *h1 = p1;
+ const struct hitsbytarget *h2 = p2;
+ return h2->hits - h1->hits;
+}
+
+// Compares two hitsbytarget nodes by hitcount
+static int cmp_ht_approx(const void *p1, const void *p2)
+{
+ const struct hitsbytarget *h1 = p1;
+ const struct hitsbytarget *h2 = p2;
+ return h2->approximation - h1->approximation;
+}
+
+static int targets_termlist_nb(WRBUF wrbuf, struct session *se, int num,
+ NMEM nmem, int version)
+{
+ struct hitsbytarget *ht;
+ int count, i;
+
+ ht = hitsbytarget_nb(se, &count, nmem);
+ if (version >= 2)
+ qsort(ht, count, sizeof(struct hitsbytarget), cmp_ht_approx);
+ else
+ qsort(ht, count, sizeof(struct hitsbytarget), cmp_ht);
+ for (i = 0; i < count && i < num && ht[i].hits > 0; i++)
+ {
+
+ // do only print terms which have display names
+
+ wrbuf_puts(wrbuf, "<term>\n");
+
+ wrbuf_puts(wrbuf, "<id>");
+ wrbuf_xmlputs(wrbuf, ht[i].id);
+ wrbuf_puts(wrbuf, "</id>\n");
+
+ wrbuf_puts(wrbuf, "<name>");
+ if (!ht[i].name || !ht[i].name[0])
+ wrbuf_xmlputs(wrbuf, "NO TARGET NAME");
+ else
+ wrbuf_xmlputs(wrbuf, ht[i].name);
+ wrbuf_puts(wrbuf, "</name>\n");
+
+ wrbuf_printf(wrbuf, "<frequency>" ODR_INT_PRINTF "</frequency>\n",
+ ht[i].hits);
+
+ if (version >= 2) {
+ // Should not print if we know it isn't a approximation.
+ wrbuf_printf(wrbuf, "<approximation>" ODR_INT_PRINTF "</approximation>\n", ht[i].approximation);
+ wrbuf_printf(wrbuf, "<records>%d</records>\n", ht[i].records - ht[i].filtered);
+ wrbuf_printf(wrbuf, "<filtered>%d</filtered>\n", ht[i].filtered);
+ }
+
+ wrbuf_puts(wrbuf, "<state>");
+ wrbuf_xmlputs(wrbuf, ht[i].state);
+ wrbuf_puts(wrbuf, "</state>\n");
+
+ wrbuf_printf(wrbuf, "<diagnostic>%d</diagnostic>\n",
+ ht[i].diagnostic);
+ wrbuf_puts(wrbuf, "</term>\n");
+ }
+ return count;
+}
+
+void perform_termlist(struct http_channel *c, struct session *se,
+ const char *name, int num, int version)
+{
+ int i, j;
+ NMEM nmem_tmp = nmem_create();
+ char **names;
+ int num_names = 0;
+
+ if (!name)
+ name = "*";
+
+ nmem_strsplit(nmem_tmp, ",", name, &names, &num_names);