Fix Savannah bug #15056 and use pscmap service in psaux module.

* include/freetype/internal/services/svpscmap.h (PS_UniMap): Use
FT_UInt32 for `glyph_index'.
(PS_Unicodes_InitFunc): Use FT_String for `glyph_names'.
(PS_Unicodes_CharIndexFunc): Use FT_UInt32 for `unicode'.
(PS_Unicodes_CharNextFunc): Make second argument a pointer to
FT_UInt32.

* src/psnames/psmodule.c (VARIANT_BIT, BASE_GLYPH): New macros.
(ps_unicode_value): Set VARIANT_BIT in return value if glyph is a
variant glyph (this is, it has non-leading `.' in its name).
(compare_uni_maps): Sort base glyphs before variant glyphs.
(ps_unicodes_init): Use FT_String for `glyph_names' argument.
Reallocate only if number of used entries is much smaller.
Updated to handle variant glyphs.
(ps_unicodes_char_index, ps_unicodes_char_next): Prefer base glyphs
over variant glyphs.
Simplify code.

* src/psaux/t1cmap.c (t1_cmap_uni_pair_compare): Removed.
(t1_cmap_unicode_init, t1_cmap_unicode_char_index,
t1_cmap_unicode_char_next): Use pscmap service.
(t1_cmap_unicode_done): Updated.

* src/psaux/t1cmap.h (T1_CMapUniPair): Removed.
(T1_CMapUnicode): Use PS_Unicodes structure.
diff --git a/ChangeLog b/ChangeLog
index ba03a7d..f720b4e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,22 +1,53 @@
-2006-01-11  suzuki toshiya <mpsuzuki@hiroshima-u.ac.jp>
+2006-01-10  Werner Lemberg  <wl@gnu.org>
 
-	Jumbo patch to fix "deprecated" warning to cross-build for
-	Tiger on Intel, the issue is reported by Sean McBride
-	<sean@rogue-research.com> on 2005-08-24.
+	Fix Savannah bug #15056 and use pscmap service in psaux module.
 
-	* src/base/ftmac.c: Heavy change to build without deprecated
-	Carbon functions on Tiger.
+	* include/freetype/internal/services/svpscmap.h (PS_UniMap): Use
+	FT_UInt32 for `glyph_index'.
+	(PS_Unicodes_InitFunc): Use FT_String for `glyph_names'.
+	(PS_Unicodes_CharIndexFunc): Use FT_UInt32 for `unicode'.
+	(PS_Unicodes_CharNextFunc): Make second argument a pointer to
+	FT_UInt32.
 
-	* builds/unix/configure.ac: Add options and autochecks for
-	Carbon functions availabilities, for MacOS X.
+	* src/psnames/psmodule.c (VARIANT_BIT, BASE_GLYPH): New macros.
+	(ps_unicode_value): Set VARIANT_BIT in return value if glyph is a
+	variant glyph (this is, it has non-leading `.' in its name).
+	(compare_uni_maps): Sort base glyphs before variant glyphs.
+	(ps_unicodes_init): Use FT_String for `glyph_names' argument.
+	Reallocate only if number of used entries is much smaller.
+	Updated to handle variant glyphs.
+	(ps_unicodes_char_index, ps_unicodes_char_next): Prefer base glyphs
+	over variant glyphs.
+	Simplify code.
 
-	* builds/mac/ascii2mpw.py: Add convertor for character "\305".
+	* src/psaux/t1cmap.c (t1_cmap_uni_pair_compare): Removed.
+	(t1_cmap_unicode_init, t1_cmap_unicode_char_index,
+	t1_cmap_unicode_char_next): Use pscmap service.
+	(t1_cmap_unicode_done): Updated.
+
+	* src/psaux/t1cmap.h (T1_CMapUniPair): Removed.
+	(T1_CMapUnicode): Use PS_Unicodes structure.
+
+2006-01-11  suzuki toshiya  <mpsuzuki@hiroshima-u.ac.jp>
+
+	Jumbo patch to fix `deprecated' warning of cross-build for Tiger on
+	Intel, as reported by Sean McBride <sean@rogue-research.com> on
+	2005-08-24.
+
+	* src/base/ftmac.c: Heavy change to build without deprecated Carbon
+	functions on Tiger.
+
+	* builds/unix/configure.ac: Add options and autochecks for Carbon
+	functions availabilities, for MacOS X.
+
+	* builds/mac/ascii2mpw.py: Add converter for character `\305'.
 	* builds/mac/FreeType.m68k_{far|cfm}.make.txt: Add conditional
-	macros to avoid unavailable functions. And ftmac.c must be
-	compiled without "-strict ansi", because it disables cpp macro
-	to use ToolBox system call.
-	* builds/mac/FreeType.ppc_{classic|carbon}.make.txt: Add
-	conditional macros to avoid unavailable functions.
+	macros to avoid unavailable functions.
+	ftmac.c must be compiled without `-strict ansi', because it disables
+	cpp macro to use ToolBox system call.
+
+	* builds/mac/FreeType.ppc_{classic|carbon}.make.txt: Add conditional
+	macros to avoid unavailable functions.
 
 	* builds/mac/README: Detailed notes on function availabilities.
 
diff --git a/include/freetype/internal/services/svpscmap.h b/include/freetype/internal/services/svpscmap.h
index ade96ef..74d57f9 100644
--- a/include/freetype/internal/services/svpscmap.h
+++ b/include/freetype/internal/services/svpscmap.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType PostScript charmap service (specification).             */
 /*                                                                         */
-/*  Copyright 2003 by                                                      */
+/*  Copyright 2003, 2006 by                                                */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -27,7 +27,7 @@
 
 
   /*
-   *  Adobe glyph name to unicode value
+   *  Adobe glyph name to unicode value.
    */
   typedef FT_UInt32
   (*PS_Unicode_ValueFunc)( const char*  glyph_name );
@@ -58,8 +58,8 @@
    */
   typedef struct  PS_UniMap_
   {
-    FT_UInt  unicode;
-    FT_UInt  glyph_index;
+    FT_UInt32  unicode;      /* bit 31 set: is glyph variant */
+    FT_UInt    glyph_index;
 
   } PS_UniMap;
 
@@ -75,16 +75,16 @@
   typedef FT_Error
   (*PS_Unicodes_InitFunc)( FT_Memory     memory,
                            FT_UInt       num_glyphs,
-                           const char**  glyph_names,
+                           FT_String**   glyph_names,
                            PS_Unicodes*  unicodes );
 
   typedef FT_UInt
   (*PS_Unicodes_CharIndexFunc)( PS_Unicodes*  unicodes,
-                                FT_UInt       unicode );
+                                FT_UInt32     unicode );
 
   typedef FT_ULong
   (*PS_Unicodes_CharNextFunc)( PS_Unicodes*  unicodes,
-                               FT_ULong      unicode );
+                               FT_UInt32    *unicode );
 
 
   FT_DEFINE_SERVICE( PsCMaps )
diff --git a/src/psaux/t1cmap.c b/src/psaux/t1cmap.c
index dcd99be..a0e25e2 100644
--- a/src/psaux/t1cmap.c
+++ b/src/psaux/t1cmap.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Type 1 character map support (body).                                 */
 /*                                                                         */
-/*  Copyright 2002, 2003 by                                                */
+/*  Copyright 2002, 2003, 2006 by                                          */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -257,105 +257,30 @@
   /*************************************************************************/
   /*************************************************************************/
 
-  FT_CALLBACK_DEF( FT_Int )
-  t1_cmap_uni_pair_compare( const void*  pair1,
-                            const void*  pair2 )
-  {
-    FT_UInt32  u1 = ((T1_CMapUniPair)pair1)->unicode;
-    FT_UInt32  u2 = ((T1_CMapUniPair)pair2)->unicode;
-
-
-    if ( u1 < u2 )
-      return -1;
-
-    if ( u1 > u2 )
-      return +1;
-
-    return 0;
-  }
-
-
   FT_CALLBACK_DEF( FT_Error )
   t1_cmap_unicode_init( T1_CMapUnicode  cmap )
   {
-    FT_Error            error;
-    FT_UInt             count;
     T1_Face             face    = (T1_Face)FT_CMAP_FACE( cmap );
     FT_Memory           memory  = FT_FACE_MEMORY( face );
     FT_Service_PsCMaps  psnames = (FT_Service_PsCMaps)face->psnames;
 
 
-    cmap->num_pairs = 0;
-    cmap->pairs     = NULL;
-
-    count = face->type1.num_glyphs;
-
-    if ( !FT_NEW_ARRAY( cmap->pairs, count ) )
-    {
-      FT_UInt         n, new_count;
-      T1_CMapUniPair  pair;
-      FT_UInt32       uni_code;
-
-
-      pair = cmap->pairs;
-      for ( n = 0; n < count; n++ )
-      {
-        const char*  gname = face->type1.glyph_names[n];
-
-
-        /* build unsorted pair table by matching glyph names */
-        if ( gname )
-        {
-          uni_code = psnames->unicode_value( gname );
-
-          if ( uni_code != 0 )
-          {
-            pair->unicode = uni_code;
-            pair->gindex  = n;
-            pair++;
-          }
-        }
-      }
-
-      new_count = (FT_UInt)( pair - cmap->pairs );
-      if ( new_count == 0 )
-      {
-        /* there are no unicode characters in here! */
-        FT_FREE( cmap->pairs );
-        error = PSaux_Err_Invalid_Argument;
-      }
-      else
-      {
-        /* re-allocate if the new array is much smaller than the original */
-        /* one                                                            */
-        if ( new_count != count && new_count < count / 2 )
-        {
-          (void)FT_RENEW_ARRAY( cmap->pairs, count, new_count );
-          error = 0;
-        }
-
-        /* sort the pairs table to allow efficient binary searches */
-        ft_qsort( cmap->pairs,
-                  new_count,
-                  sizeof ( T1_CMapUniPairRec ),
-                  t1_cmap_uni_pair_compare );
-
-        cmap->num_pairs = new_count;
-      }
-    }
-
-    return error;
+    return psnames->unicodes_init( memory,
+                                   face->type1.num_glyphs,
+                                   face->type1.glyph_names,
+                                   &cmap->unicodes );
   }
 
 
   FT_CALLBACK_DEF( void )
   t1_cmap_unicode_done( T1_CMapUnicode  cmap )
   {
-    FT_Face    face   = FT_CMAP_FACE(cmap);
-    FT_Memory  memory = FT_FACE_MEMORY(face);
+    FT_Face    face   = FT_CMAP_FACE( cmap );
+    FT_Memory  memory = FT_FACE_MEMORY( face );
 
-    FT_FREE( cmap->pairs );
-    cmap->num_pairs = 0;
+
+    FT_FREE( cmap->unicodes.maps );
+    cmap->unicodes.num_maps = 0;
   }
 
 
@@ -363,26 +288,11 @@
   t1_cmap_unicode_char_index( T1_CMapUnicode  cmap,
                               FT_UInt32       char_code )
   {
-    FT_UInt         min = 0;
-    FT_UInt         max = cmap->num_pairs;
-    FT_UInt         mid;
-    T1_CMapUniPair  pair;
+    T1_Face             face    = (T1_Face)FT_CMAP_FACE( cmap );
+    FT_Service_PsCMaps  psnames = (FT_Service_PsCMaps)face->psnames;
 
 
-    while ( min < max )
-    {
-      mid  = min + ( max - min ) / 2;
-      pair = cmap->pairs + mid;
-
-      if ( pair->unicode == char_code )
-        return pair->gindex;
-
-      if ( pair->unicode < char_code )
-        min = mid + 1;
-      else
-        max = mid;
-    }
-    return 0;
+    return psnames->unicodes_char_index( &cmap->unicodes, char_code );
   }
 
 
@@ -390,54 +300,11 @@
   t1_cmap_unicode_char_next( T1_CMapUnicode  cmap,
                              FT_UInt32      *pchar_code )
   {
-    FT_UInt    result    = 0;
-    FT_UInt32  char_code = *pchar_code + 1;
+    T1_Face             face    = (T1_Face)FT_CMAP_FACE( cmap );
+    FT_Service_PsCMaps  psnames = (FT_Service_PsCMaps)face->psnames;
 
 
-  Restart:
-    {
-      FT_UInt         min = 0;
-      FT_UInt         max = cmap->num_pairs;
-      FT_UInt         mid;
-      T1_CMapUniPair  pair;
-
-
-      while ( min < max )
-      {
-        mid  = min + ( ( max - min ) >> 1 );
-        pair = cmap->pairs + mid;
-
-        if ( pair->unicode == char_code )
-        {
-          result = pair->gindex;
-          if ( result != 0 )
-            goto Exit;
-
-          char_code++;
-          goto Restart;
-        }
-
-        if ( pair->unicode < char_code )
-          min = mid+1;
-        else
-          max = mid;
-      }
-
-      /* we didn't find it, but we have a pair just above it */
-      char_code = 0;
-
-      if ( min < cmap->num_pairs )
-      {
-        pair   = cmap->pairs + min;
-        result = pair->gindex;
-        if ( result != 0 )
-          char_code = pair->unicode;
-      }
-    }
-
-  Exit:
-    *pchar_code = char_code;
-    return result;
+    return psnames->unicodes_char_next( &cmap->unicodes, pchar_code );
   }
 
 
diff --git a/src/psaux/t1cmap.h b/src/psaux/t1cmap.h
index aa93d74..5382efc 100644
--- a/src/psaux/t1cmap.h
+++ b/src/psaux/t1cmap.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Type 1 character map support (specification).                        */
 /*                                                                         */
-/*  Copyright 2002, 2003 by                                                */
+/*  Copyright 2002, 2003, 2006 by                                          */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -89,22 +89,13 @@
   /*************************************************************************/
   /*************************************************************************/
 
-  /* unicode (syntehtic) cmaps */
+  /* unicode (synthetic) cmaps */
   typedef struct T1_CMapUnicodeRec_*  T1_CMapUnicode;
 
-  typedef struct  T1_CMapUniPairRec_
-  {
-    FT_UInt32  unicode;
-    FT_UInt    gindex;
-
-  } T1_CMapUniPairRec, *T1_CMapUniPair;
-
-
   typedef struct  T1_CMapUnicodeRec_
   {
-    FT_CMapRec      cmap;
-    FT_UInt         num_pairs;
-    T1_CMapUniPair  pairs;
+    FT_CMapRec   cmap;
+    PS_Unicodes  unicodes;
 
   } T1_CMapUnicodeRec;
 
diff --git a/src/psnames/psmodule.c b/src/psnames/psmodule.c
index ba9deae..db8b25f 100644
--- a/src/psnames/psmodule.c
+++ b/src/psnames/psmodule.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    PSNames module implementation (body).                                */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002, 2003, 2005 by                               */
+/*  Copyright 1996-2001, 2002, 2003, 2005, 2006 by                         */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -32,9 +32,14 @@
 #ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST
 
 
+#define VARIANT_BIT         ( 1L << 31 )
+#define BASE_GLYPH( code )  ( (code) & ~VARIANT_BIT )
+
+
   /* Return the Unicode value corresponding to a given glyph.  Note that */
   /* we do deal with glyph variants by detecting a non-initial dot in    */
-  /* the name, as in `A.swash' or `e.final'.                             */
+  /* the name, as in `A.swash' or `e.final'; in this case, the           */
+  /* VARIANT_BIT is set in the return value.                             */
   /*                                                                     */
   static FT_UInt32
   ps_unicode_value( const char*  glyph_name )
@@ -72,7 +77,9 @@
             d += 10;
         }
 
-        /* exit if a non-uppercase hexadecimal character was found */
+        /* Exit if a non-uppercase hexadecimal character was found   */
+        /* -- this also catches character codes below `0' since such */
+        /* negative numbers cast to `unsigned int' are far too big.  */
         if ( d >= 16 )
           break;
 
@@ -80,8 +87,13 @@
       }
 
       /* there must be exactly four hex digits */
-      if ( ( *p == '\0' || *p == '.' ) && count == 0 )
-        return value;
+      if ( count == 0 )
+      {
+        if ( *p == '\0' )
+          return value;
+        if ( *p == '.' )
+          return value ^ VARIANT_BIT;
+      }
     }
 
     /* If the name begins with `u', followed by four to six uppercase */
@@ -115,12 +127,17 @@
         value = ( value << 4 ) + d;
       }
 
-      if ( ( *p == '\0' || *p == '.' ) && count <= 2 )
-        return value;
+      if ( count <= 2 )
+      {
+        if ( *p == '\0' )
+          return value;
+        if ( *p == '.' )
+          return value ^ VARIANT_BIT;
+      }
     }
 
-    /* look for a non-initial dot in the glyph name in order to */
-    /* sort-out variants like `A.swash', `e.final', etc.        */
+    /* Look for a non-initial dot in the glyph name in order to */
+    /* find variants like `A.swash', `e.final', etc.            */
     {
       const char*  p   = glyph_name;
       const char*  dot = NULL;
@@ -128,15 +145,18 @@
 
       for ( ; *p; p++ )
       {
-        if ( *p == '.' && p > glyph_name && !dot )
+        if ( *p == '.' && p > glyph_name )
+        {
           dot = p;
+          break;
+        }
       }
 
+      /* now look up the glyph in the Adobe Glyph List */
       if ( !dot )
-        dot = p;
-
-      /* now, look up the glyph in the Adobe Glyph List */
-      return ft_get_adobe_glyph_index( glyph_name, dot );
+        return ft_get_adobe_glyph_index( glyph_name, p );
+      else
+        return ft_get_adobe_glyph_index( glyph_name, dot ) ^ VARIANT_BIT;
     }
   }
 
@@ -148,17 +168,23 @@
   {
     PS_UniMap*  map1 = (PS_UniMap*)a;
     PS_UniMap*  map2 = (PS_UniMap*)b;
+    FT_UInt32   unicode1 = BASE_GLYPH( map1->unicode );
+    FT_UInt32   unicode2 = BASE_GLYPH( map2->unicode );
 
 
-    return ( map1->unicode - map2->unicode );
+    /* sort base glyphs before glyph variants */
+    if ( unicode1 == unicode2 )
+      return map1->unicode - map2->unicode;
+    else
+      return unicode1 - unicode2;
   }
 
 
-  /* Builds a table that maps Unicode values to glyph indices */
+  /* Build a table that maps Unicode values to glyph indices. */
   static FT_Error
   ps_unicodes_init( FT_Memory     memory,
                     FT_UInt       num_glyphs,
-                    const char**  glyph_names,
+                    FT_String**   glyph_names,
                     PS_Unicodes*  table )
   {
     FT_Error  error;
@@ -187,32 +213,37 @@
         {
           uni_char = ps_unicode_value( gname );
 
-          if ( uni_char != 0 && uni_char != 0xFFFFL )
+          if ( BASE_GLYPH( uni_char ) != 0 )
           {
-            map->unicode     = (FT_UInt)uni_char;
+            map->unicode     = uni_char;
             map->glyph_index = n;
             map++;
           }
         }
       }
 
-      /* now, compress the table a bit */
+      /* now compress the table a bit */
       count = (FT_UInt)( map - table->maps );
 
-      if ( count > 0 && FT_REALLOC( table->maps,
-                                    num_glyphs * sizeof ( PS_UniMap ),
-                                    count * sizeof ( PS_UniMap ) ) )
-        count = 0;
-
       if ( count == 0 )
       {
         FT_FREE( table->maps );
         if ( !error )
-          error = PSnames_Err_Invalid_Argument;  /* no unicode chars here! */
+          error = PSnames_Err_Invalid_Argument;  /* No unicode chars here! */
       }
-      else
-        /* sort the table in increasing order of unicode values */
-        ft_qsort( table->maps, count, sizeof ( PS_UniMap ), compare_uni_maps );
+      else {
+        /* Reallocate if the number of used entries is much smaller. */
+        if ( count < num_glyphs / 2 )
+        {
+          (void)FT_RENEW_ARRAY( table->maps, num_glyphs, count );
+          error = PSnames_Err_Ok;
+        }
+
+        /* Sort the table in increasing order of unicode values, */
+        /* taking care of glyph variants.                        */
+        ft_qsort( table->maps, count, sizeof ( PS_UniMap ),
+                  compare_uni_maps );
+      }
 
       table->num_maps = count;
     }
@@ -223,74 +254,105 @@
 
   static FT_UInt
   ps_unicodes_char_index( PS_Unicodes*  table,
-                          FT_ULong      unicode )
+                          FT_UInt32     unicode )
   {
-    PS_UniMap  *min, *max, *mid;
+    PS_UniMap  *min, *max, *mid, *result = NULL;
 
 
-    /* perform a binary search on the table */
+    /* Perform a binary search on the table. */
 
     min = table->maps;
     max = min + table->num_maps - 1;
 
     while ( min <= max )
     {
-      mid = min + ( max - min ) / 2;
+      FT_UInt32  base_glyph;
+
+
+      mid = min + ( ( max - min ) >> 1 );
+
       if ( mid->unicode == unicode )
-        return mid->glyph_index;
+      {
+        result = mid;
+        break;
+      }
+
+      base_glyph = BASE_GLYPH( mid->unicode );
+
+      if ( base_glyph == unicode )
+        result = mid; /* remember match but continue search for base glyph */
 
       if ( min == max )
         break;
 
-      if ( mid->unicode < unicode )
+      if ( base_glyph < unicode )
         min = mid + 1;
       else
         max = mid - 1;
     }
 
-    return 0xFFFFU;
+    if ( result )
+      return result->glyph_index;
+    else
+      return 0;
   }
 
 
   static FT_ULong
   ps_unicodes_char_next( PS_Unicodes*  table,
-                         FT_ULong      unicode )
+                         FT_UInt32    *unicode )
   {
-    PS_UniMap  *min, *max, *mid;
+    FT_UInt    result    = 0;
+    FT_UInt32  char_code = *unicode + 1;
 
 
-    unicode++;
-    /* perform a binary search on the table */
-
-    min = table->maps;
-    max = min + table->num_maps - 1;
-
-    while ( min <= max )
     {
-      mid = min + ( max - min ) / 2;
-      if ( mid->unicode == unicode )
-        return unicode;
+      FT_UInt     min = 0;
+      FT_UInt     max = table->num_maps;
+      FT_UInt     mid;
+      PS_UniMap*  map;
+      FT_UInt32   base_glyph;
 
-      if ( min == max )
-        break;
 
-      if ( mid->unicode < unicode )
-        min = mid + 1;
-      else
-        max = mid - 1;
+      while ( min < max )
+      {
+        mid = min + ( ( max - min ) >> 1 );
+        map = table->maps + mid;
+
+        if ( map->unicode == char_code )
+        {
+          result = map->glyph_index;
+          goto Exit;
+        }
+
+        base_glyph = BASE_GLYPH( map->unicode );
+
+        if ( base_glyph == char_code )
+          result = map->glyph_index;
+
+        if ( base_glyph < char_code )
+          min = mid + 1;
+        else
+          max = mid;
+      }
+
+      if ( result )
+        goto Exit;               /* we have a variant glyph */
+
+      /* we didn't find it; check whether we have a map just above it */
+      char_code = 0;
+
+      if ( min < table->num_maps )
+      {
+        map    = table->maps + min;
+        result = map->glyph_index;
+        char_code = map->unicode;
+      }
     }
 
-    if ( max < table->maps )
-      max = table->maps;
-
-    while ( max < table->maps + table->num_maps )
-    {
-      if ( unicode < max->unicode )
-        return max->unicode;
-      max++;
-    }
-
-    return 0;
+  Exit:
+    *unicode = char_code;
+    return result;
   }