+ struct record_cluster *r1 = (*(struct record_cluster**) p1);
+ struct record_cluster *r2 = (*(struct record_cluster**) p2);
+ struct reclist_sortparms *sortparms = r1->sort_parms;
+ struct reclist_sortparms *s;
+ int res = 0;
+
+ for (s = sortparms; s && res == 0; s = s->next)
+ {
+ union data_types *ut1 = r1->sortkeys[s->offset];
+ union data_types *ut2 = r2->sortkeys[s->offset];
+ const char *s1, *s2;
+ switch (s->type)
+ {
+ case Metadata_type_relevance:
+ res = r1->relevance_score - r2->relevance_score;
+ break;
+ case Metadata_type_generic:
+ case Metadata_type_skiparticle:
+ s1 = ut1 ? ut1->text.sort : "";
+ s2 = ut2 ? ut2->text.sort : "";
+ res = strcmp(s1, s2);
+ break;
+ case Metadata_type_year:
+ case Metadata_type_date:
+ if (ut1 && ut2)
+ {
+ if (s->increasing)
+ res = ut1->number.min - ut2->number.min;
+ else
+ res = ut1->number.max - ut2->number.max;
+ }
+ else if (ut1 && !ut2)
+ {
+ res = -1; /* without date/year: last! */
+ continue;
+ }
+ else if (!ut1 && ut2)
+ {
+ res = 1; /* without date/year: last! */
+ continue;
+ }
+ else
+ res = 0;
+ break;
+ case Metadata_type_position:
+ if (r1->records && r2->records)
+ {
+ int pos1 = 0, pos2 = 0;
+ struct record *rec;
+ for (rec = r1->records; rec; rec = rec->next)
+ if (pos1 == 0 || rec->position < pos1)
+ pos1 = rec->position;
+ for (rec = r2->records; rec; rec = rec->next)
+ if (pos2 == 0 || rec->position < pos2)
+ pos2 = rec->position;
+ res = pos1 - pos2;
+ continue;
+ }
+ break;
+ case Metadata_type_float:
+ if (ut1 && ut2)
+ {
+ if (ut1->fnumber == ut2->fnumber)
+ res = 0;
+ else if (ut1->fnumber > ut2->fnumber)
+ res = 1;
+ else
+ res = -1;
+ }
+ else if (ut1)
+ res = 1;
+ else if (ut2)
+ res = -1;
+ else
+ res = 0;
+ break;
+ }
+ if (res && !s->increasing)
+ res *= -1;
+ }
+ if (res == 0)
+ res = strcmp(r1->recid, r2->recid);
+ return res;
+}
+
+void reclist_limit(struct reclist *l, struct session *se, int lazy)
+{
+ unsigned i;
+ int num = 0;
+ struct record_cluster **pp = &l->sorted_list;
+
+ reclist_enter(l);
+
+ if (!lazy || !*pp)
+ {
+ for (i = 0; i < l->hash_size; i++)
+ {
+ struct reclist_bucket *p;
+ for (p = l->hashtable[i]; p; p = p->hash_next)
+ p->record->sorted_next = 0;
+ }
+ for (i = 0; i < l->hash_size; i++)
+ {
+ struct reclist_bucket *p;
+ for (p = l->hashtable[i]; p; p = p->hash_next)
+ {
+ if (session_check_cluster_limit(se, p->record))
+ {
+ if (!p->record->sorted_next)
+ {
+ *pp = p->record;
+ pp = &p->record->sorted_next;
+ *pp = p->record; /* signal already in use */
+ num++;
+ }
+ }
+ }
+ }
+ *pp = 0;
+ }
+ l->num_records = num;
+ reclist_leave(l);