]> git.eshelyaron.com Git - emacs.git/commitdiff
Properly sort results for partial font specs
authorPo Lu <luangruo@yahoo.com>
Sat, 13 Jan 2024 01:51:59 +0000 (09:51 +0800)
committerPo Lu <luangruo@yahoo.com>
Sat, 13 Jan 2024 01:51:59 +0000 (09:51 +0800)
* src/sfntfont.c (sfntfont_compare_font_entities): New function.
(sfntfont_list): Sort matching font entities by the number of
fields set, and mention why.

src/sfntfont.c

index 1ad41deac70fce11d3715dbde88e2d4d469ab606..860fc446184847ca7c122a66fe6ac7430387885a 100644 (file)
@@ -1939,13 +1939,51 @@ sfntfont_desc_to_entity (struct sfnt_font_desc *desc, int instance)
   return entity;
 }
 
+/* Return whether fewer fields inside the font entity A are set than
+   there are set inside the font entity B.  */
+
+static Lisp_Object
+sfntfont_compare_font_entities (Lisp_Object a, Lisp_Object b)
+{
+  ptrdiff_t count_a, count_b, i;
+
+  count_a = 0;
+  count_b = 0;
+
+  for (i = 0; i < FONT_ENTITY_MAX; ++i)
+    {
+      if (!NILP (AREF (a, i)))
+       count_a++;
+    }
+
+  for (i = 0; i < FONT_ENTITY_MAX; ++i)
+    {
+      if (!NILP (AREF (b, i)))
+       count_b++;
+    }
+
+  return count_a < count_b ? Qt : Qnil;
+}
+
+/* Function that compares two font entities to return whether fewer
+   fields are set within the first than in the second.  */
+
+static union Aligned_Lisp_Subr Scompare_font_entities =
+  {
+    {
+      { PSEUDOVECTOR_FLAG | (PVEC_SUBR << PSEUDOVECTOR_AREA_BITS), },
+      { .a2 = sfntfont_compare_font_entities, },
+      2, 2, "sfntfont_compare_font_entities", {0}, lisp_h_Qnil,
+    },
+  };
+
 /* Return a list of font-entities matching the specified
    FONT_SPEC.  */
 
 Lisp_Object
 sfntfont_list (struct frame *f, Lisp_Object font_spec)
 {
-  Lisp_Object matching, tem;
+  Lisp_Object matching, tem, compare_font_entities;
   struct sfnt_font_desc *desc;
   int i, rc, instances[100];
 
@@ -1982,9 +2020,16 @@ sfntfont_list (struct frame *f, Lisp_Object font_spec)
                              matching);
        }
     }
-
   unblock_input ();
 
+  /* Sort matching by the number of fields set inside each element, so
+     that values of FONT_SPECs that leave a number of fields
+     unspecified will yield a list with the closest matches (that is
+     to say, those whose fields are precisely as specified by the
+     caller) ordered first.  */
+
+  XSETSUBR (compare_font_entities, &Scompare_font_entities.s);
+  matching = Fsort (matching, compare_font_entities);
   return matching;
 }