[name] More

It assumes all names are encoded in UTF16-BE.  Other than that, and not
listing languages correctly, it's *supposed* to work.
diff --git a/src/hb-dsalgs.hh b/src/hb-dsalgs.hh
index d22e880..265651b 100644
--- a/src/hb-dsalgs.hh
+++ b/src/hb-dsalgs.hh
@@ -313,6 +313,27 @@
  */
 
 static inline void *
+hb_bsearch (const void *key, const void *base,
+	    size_t nmemb, size_t size,
+	    int (*compar)(const void *_key, const void *_item))
+{
+  int min = 0, max = (int) nmemb - 1;
+  while (min <= max)
+  {
+    int mid = (min + max) / 2;
+    const void *p = (const void *) (((const char *) base) + (mid * size));
+    int c = compar (key, p);
+    if (c < 0)
+      max = mid - 1;
+    else if (c > 0)
+      min = mid + 1;
+    else
+      return (void *) p;
+  }
+  return nullptr;
+}
+
+static inline void *
 hb_bsearch_r (const void *key, const void *base,
 	      size_t nmemb, size_t size,
 	      int (*compar)(const void *_key, const void *_item, void *_arg),
diff --git a/src/hb-ot-name-table.hh b/src/hb-ot-name-table.hh
index 8967fcb..f2eb496 100644
--- a/src/hb-ot-name-table.hh
+++ b/src/hb-ot-name-table.hh
@@ -107,20 +107,31 @@
 };
 
 static int
-_hb_ot_name_entry_cmp (const void *pa, const void *pb)
+_hb_ot_name_entry_cmp_key (const void *pa, const void *pb)
 {
   const hb_ot_name_entry_t *a = (const hb_ot_name_entry_t *) pa;
   const hb_ot_name_entry_t *b = (const hb_ot_name_entry_t *) pb;
 
-  /* Sort by name_id, then language, then score, then index. */
+  /* Compare by name_id, then language. */
 
   if (a->name_id != b->name_id)
     return a->name_id < b->name_id ? -1 : +1;
 
-  int e = strcmp (hb_language_to_string (a->language),
-		  hb_language_to_string (b->language));
-  if (e)
-    return e;
+  return strcmp (hb_language_to_string (a->language),
+		 hb_language_to_string (b->language));
+}
+
+static int
+_hb_ot_name_entry_cmp (const void *pa, const void *pb)
+{
+  /* Compare by name_id, then language, then score, then index. */
+
+  int v = _hb_ot_name_entry_cmp_key (pa, pb);
+  if (v)
+    return v;
+
+  const hb_ot_name_entry_t *a = (const hb_ot_name_entry_t *) pa;
+  const hb_ot_name_entry_t *b = (const hb_ot_name_entry_t *) pb;
 
   if (a->entry_score != b->entry_score)
     return a->entry_score < b->entry_score ? -1 : +1;
@@ -199,13 +210,25 @@
       this->names.resize (j);
     }
 
-
     inline void fini (void)
     {
       this->names.fini ();
       hb_blob_destroy (this->blob);
     }
 
+    inline int get_index (hb_name_id_t   name_id,
+			  hb_language_t  language) const
+    {
+      const hb_ot_name_entry_t key = {name_id, {0}, language};
+      const hb_ot_name_entry_t *entry = (const hb_ot_name_entry_t *)
+					hb_bsearch (&key,
+						    this->names.arrayZ(),
+						    this->names.len,
+						    sizeof (key),
+						    _hb_ot_name_entry_cmp_key);
+      return entry ? entry->entry_index : -1;
+    }
+
     private:
     hb_blob_t *blob;
     public:
diff --git a/src/hb-ot-name.cc b/src/hb-ot-name.cc
index fe1276c..626e063 100644
--- a/src/hb-ot-name.cc
+++ b/src/hb-ot-name.cc
@@ -105,11 +105,15 @@
 		    typename utf_t::codepoint_t *text /* OUT */)
 {
   const OT::name_accelerator_t &name = _get_name (face);
-  unsigned int idx = 0; // XXX bsearch and find
-  hb_bytes_t bytes = name.table->get_name (idx);
 
-  if (true /*UTF16-BE*/)
-    return hb_ot_name_convert_utf<hb_utf16_be_t, utf_t> (&bytes, text_size, text);
+  int idx = name.get_index (name_id, language);
+  if (idx != -1)
+  {
+    hb_bytes_t bytes = name.table->get_name (idx);
+
+    if (true /*UTF16-BE*/)
+      return hb_ot_name_convert_utf<hb_utf16_be_t, utf_t> (&bytes, text_size, text);
+  }
 
   if (text_size)
   {
diff --git a/src/hb-ot-os2-unicode-ranges.hh b/src/hb-ot-os2-unicode-ranges.hh
index 1978008..b0ccd00 100644
--- a/src/hb-ot-os2-unicode-ranges.hh
+++ b/src/hb-ot-os2-unicode-ranges.hh
@@ -34,7 +34,7 @@
 struct OS2Range
 {
   static int
-  cmp (const void *_key, const void *_item, void *_arg)
+  cmp (const void *_key, const void *_item)
   {
     hb_codepoint_t cp = *((hb_codepoint_t *) _key);
     const OS2Range *range = (OS2Range *) _item;
@@ -233,10 +233,10 @@
 static unsigned int
 _hb_ot_os2_get_unicode_range_bit (hb_codepoint_t cp)
 {
-  OS2Range *range = (OS2Range*) hb_bsearch_r (&cp, _hb_os2_unicode_ranges,
-					      ARRAY_LENGTH (_hb_os2_unicode_ranges),
-					      sizeof (OS2Range),
-					      OS2Range::cmp, nullptr);
+  OS2Range *range = (OS2Range*) hb_bsearch (&cp, _hb_os2_unicode_ranges,
+					    ARRAY_LENGTH (_hb_os2_unicode_ranges),
+					    sizeof (OS2Range),
+					    OS2Range::cmp);
   if (range != nullptr)
     return range->bit;
   return -1;
diff --git a/src/hb-unicode.cc b/src/hb-unicode.cc
index 596e76d..a08f888 100644
--- a/src/hb-unicode.cc
+++ b/src/hb-unicode.cc
@@ -576,8 +576,8 @@
 bool
 _hb_unicode_is_emoji_Extended_Pictographic (hb_codepoint_t cp)
 {
-  return hb_bsearch_r (&cp, _hb_unicode_emoji_Extended_Pictographic_table,
-		       ARRAY_LENGTH (_hb_unicode_emoji_Extended_Pictographic_table),
-		       sizeof (hb_unicode_range_t),
-		       hb_unicode_range_t::cmp, nullptr);
+  return hb_bsearch (&cp, _hb_unicode_emoji_Extended_Pictographic_table,
+		     ARRAY_LENGTH (_hb_unicode_emoji_Extended_Pictographic_table),
+		     sizeof (hb_unicode_range_t),
+		     hb_unicode_range_t::cmp);
 }
diff --git a/src/hb-unicode.hh b/src/hb-unicode.hh
index 6d6a4fa..4326798 100644
--- a/src/hb-unicode.hh
+++ b/src/hb-unicode.hh
@@ -369,7 +369,7 @@
 struct hb_unicode_range_t
 {
   static int
-  cmp (const void *_key, const void *_item, void *_arg)
+  cmp (const void *_key, const void *_item)
   {
     hb_codepoint_t cp = *((hb_codepoint_t *) _key);
     const hb_unicode_range_t *range = (hb_unicode_range_t *) _item;