+ struct reclist_sortparms *sortparms =
+ (*(struct reclist_bucket **) p1)->sort_parms;
+ struct record_cluster *r1 = (*(struct reclist_bucket**) p1)->record;
+ struct record_cluster *r2 = (*(struct reclist_bucket**) p2)->record;
+ 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_sortkey_relevance:
+ res = r2->relevance_score - r1->relevance_score;
+ break;
+ case Metadata_sortkey_string:
+ s1 = ut1 ? ut1->text.sort : "";
+ s2 = ut2 ? ut2->text.sort : "";
+ res = strcmp(s2, s1);
+ if (res)
+ {
+ if (s->increasing)
+ res *= -1;
+ }
+ break;
+ case Metadata_sortkey_numeric:
+ if (ut1 && ut2)
+ {
+ if (s->increasing)
+ res = ut1->number.min - ut2->number.min;
+ else
+ res = ut2->number.max - ut1->number.max;
+ }
+ else if (ut1 && !ut2)
+ res = -1;
+ else if (!ut1 && ut2)
+ res = 1;
+ else
+ res = 0;
+ break;
+ case Metadata_sortkey_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;
+ if (s->increasing)
+ res = pos1 - pos2;
+ else
+ res = pos2 - pos1;
+ }
+ break;
+ default:
+ yaz_log(YLOG_WARN, "Bad sort type: %d", s->type);
+ res = 0;
+ }
+ }
+ if (res == 0)
+ res = strcmp(r1->recid, r2->recid);
+ return res;