Index: pango/modules.c
===================================================================
RCS file: /cvs/gnome/pango/pango/modules.c,v
retrieving revision 1.41
diff -u -r1.41 modules.c
--- pango/modules.c	7 Dec 2002 00:54:27 -0000	1.41
+++ pango/modules.c	18 Jul 2003 22:21:40 -0000
@@ -39,7 +39,7 @@
   gboolean is_leaf;
   union {
     PangoMapEntry entry;
-    PangoMapEntry *leaves;
+    PangoSubmap *leaves;
   } d;
 };
 
@@ -74,6 +74,8 @@
 static void build_map    (PangoMapInfo *info);
 static void init_modules (void);
 
+#define LEAVES 64
+
 /**
  * pango_find_map:
  * @language: the language tag for which to find the map
@@ -402,90 +404,99 @@
   read_modules ();
 }
 
-static PangoSubmap *
-map_get_submap (PangoMap *map,
-		int       index)
-{
-  if (index >= map->n_submaps)
-    {
-      /* Round up to a multiple of 256 */
-      int new_n_submaps = (index + 0x100) & ~0xff;
-      int i;
-      
-      map->submaps = g_renew (PangoSubmap, map->submaps, new_n_submaps);
-      for (i=map->n_submaps; i<new_n_submaps; i++)
-	{
-	  map->submaps[i].is_leaf = TRUE;
-	  map->submaps[i].d.entry.info = NULL;
-	  map->submaps[i].d.entry.is_exact = FALSE;
-	}
-      
-      map->n_submaps = new_n_submaps;
-    }
-
-  return &map->submaps[index];
-}
-
 static void
 map_add_engine (PangoMapInfo    *info,
 		PangoEnginePair *pair)
 {
-  int submap;
-  int i, j;
-  PangoMap *map = info->map;
- 
-  for (i=0; i<pair->info.n_ranges; i++)
+  gint i, j, k, l; 
+
+  for (i = 0; i < pair->info.n_ranges; i++)
     {
       gboolean is_exact = FALSE;
 
+      g_return_if_fail (pair->info.ranges[i].start >= 0 
+                        && pair->info.ranges[i].end <= 0x10ffff);
+
       if (pair->info.ranges[i].langs)
 	{
 	  if (pango_language_matches (info->language, pair->info.ranges[i].langs))
 	    is_exact = TRUE;
 	}
-      
-      for (submap = pair->info.ranges[i].start / 256;
-	   submap <= pair->info.ranges[i].end / 256;
-	   submap ++)
-	{
-	  PangoSubmap *submap_struct = map_get_submap (map, submap);
-	  gunichar start;
-	  gunichar end;
 
-	  if (submap == pair->info.ranges[i].start / 256)
-	    start = pair->info.ranges[i].start % 256;
-	  else
-	    start = 0;
-	  
-	  if (submap == pair->info.ranges[i].end / 256)
-	    end = pair->info.ranges[i].end % 256;
-	  else
-	    end = 255;
-	  
-	  if (submap_struct->is_leaf &&
-	      start == 0 && end == 255)
-	    {
-	      set_entry (&submap_struct->d.entry,
-			 is_exact, &pair->info);
-	    }
-	  else
-	    {
-	      if (submap_struct->is_leaf)
-		{
-		  PangoMapEntry old_entry = submap_struct->d.entry;
-		  
-		  submap_struct->is_leaf = FALSE;
-		  submap_struct->d.leaves = g_new (PangoMapEntry, 256);
-		  for (j=0; j<256; j++)
-		    submap_struct->d.leaves[j] = old_entry;
-		}
-	      
-	      for (j=start; j<=end; j++)
-		set_entry (&submap_struct->d.leaves[j],
-			   is_exact, &pair->info);
-	      
-	    }
-	}
+      for (j = pair->info.ranges[i].start / (LEAVES*LEAVES);
+           j <= pair->info.ranges[i].end / (LEAVES*LEAVES);
+           j++)
+        {
+          PangoSubmap *submap = &info->map->submaps[j];
+          gunichar start, end;
+
+          if (j == pair->info.ranges[i].start / (LEAVES*LEAVES))
+            start = pair->info.ranges[i].start % (LEAVES*LEAVES);
+          else
+            start = 0;
+
+          if (j == pair->info.ranges[i].end / (LEAVES*LEAVES))
+	    end = pair->info.ranges[i].end % (LEAVES*LEAVES);
+          else
+            end = LEAVES*LEAVES-1;
+
+          if (start == 0 && end == LEAVES*LEAVES-1 && submap->is_leaf)
+            set_entry (&submap->d.entry, is_exact, &pair->info);
+          else
+            {
+              if (submap->is_leaf)
+                {
+                  PangoMapEntry old_entry = submap->d.entry;
+                  gint x;
+
+                  submap->is_leaf = FALSE;
+                  submap->d.leaves = g_new (PangoSubmap, LEAVES);
+		  for (x = 0; x < LEAVES; x++)
+                    {
+                      submap->d.leaves[x].is_leaf = TRUE;
+                      submap->d.leaves[x].d.entry = old_entry;
+                    }
+                }
+
+              for (k = start / LEAVES; k <= end / LEAVES; k++)
+                {
+                  PangoSubmap *submap2 = &submap->d.leaves[k%LEAVES];
+                  gunichar start2, end2;
+
+                  if (k == (pair->info.ranges[i].start / LEAVES) % LEAVES)
+                    start2 = pair->info.ranges[i].start % LEAVES;
+                  else
+                    start2 = 0;
+
+                  if (k == (pair->info.ranges[i].end / LEAVES) % LEAVES)
+                    end2 = pair->info.ranges[i].end % LEAVES;
+                  else
+                    end2 = LEAVES - 1;
+
+                  if (start2 == 0 && end2 == LEAVES - 1 && submap2->is_leaf)
+                    set_entry (&submap2->d.entry, is_exact, &pair->info);
+                  else
+                    {
+                      if (submap2->is_leaf)
+                        {
+                          PangoMapEntry old_entry = submap2->d.entry;
+                          gint x;
+
+                          submap2->is_leaf = FALSE;
+                          submap2->d.leaves = g_new (PangoSubmap, LEAVES);
+                          for (x = 0; x < LEAVES;  x++)
+                            {
+                              submap2->d.leaves[x].is_leaf = TRUE;
+                              submap2->d.leaves[x].d.entry = old_entry;
+                            }
+                        }
+
+                      for (l = start2; l <= end2; l++)
+                        set_entry (&submap2->d.leaves[l].d.entry, is_exact, &pair->info);
+                    }
+                }
+            }
+        }
     }
 }
 
@@ -514,6 +525,7 @@
 build_map (PangoMapInfo *info)
 {
   PangoMap *map;
+  gint i;
 
   const char *engine_type = g_quark_to_string (info->engine_type_id);
   const char *render_type = g_quark_to_string (info->render_type_id);
@@ -541,14 +553,42 @@
     }
   
   info->map = map = g_new (PangoMap, 1);
-  map->submaps = NULL;
-  map->n_submaps = 0;
+  map->n_submaps = 0x110000 / (LEAVES * LEAVES); 
+  map->submaps = g_new (PangoSubmap, map->n_submaps);
+  for (i = 0; i < map->n_submaps; i++)
+    {
+      map->submaps[i].is_leaf = TRUE;
+      map->submaps[i].d.entry.info = NULL;
+      map->submaps[i].d.entry.is_exact = FALSE;
+    }
 
   map_add_engine_list (info, dlloaded_engines, engine_type, render_type);  
   map_add_engine_list (info, registered_engines, engine_type, render_type);  
   map_add_engine_list (info, builtin_engines, engine_type, render_type);  
 }
 
+static PangoSubmap *
+find_submap (PangoMap   *map,
+             gunichar    wc)
+{       
+  if (wc/(LEAVES*LEAVES) < map->n_submaps)
+    {
+      PangoSubmap *submap = &map->submaps[wc/(LEAVES*LEAVES)];
+      if (submap->is_leaf)
+        return submap;
+      else 
+        {
+          submap = &submap->d.leaves[(wc/LEAVES)%LEAVES];
+          if (submap->is_leaf)
+            return submap;
+          else
+            return &submap->d.leaves[wc%LEAVES];
+        }
+    }
+
+  return NULL;
+}
+
 /**
  * pango_map_get_entry:
  * @map: a #PangoMap
@@ -564,15 +604,12 @@
  **/
 PangoMapEntry *
 pango_map_get_entry (PangoMap   *map,
-		     guint32     wc)
+		     gunichar    wc)
 {
-  int i = wc / 256;
+  PangoSubmap *submap = find_submap (map, wc);
 
-  if (i < map->n_submaps)
-    {
-      PangoSubmap *submap = &map->submaps[i];
-      return submap->is_leaf ? &submap->d.entry : &submap->d.leaves[wc % 256];
-    }
+  if (submap)
+    return &submap->d.entry;
   else
     {
       static PangoMapEntry default_entry = { NULL, FALSE };
@@ -595,12 +632,11 @@
 pango_map_get_engine (PangoMap *map,
 		      guint32   wc)
 {
-  int i = wc / 256;
+  PangoSubmap *submap = find_submap (map, wc);
 
-  if (i < map->n_submaps)
+  if (submap)
     {
-      PangoSubmap *submap = &map->submaps[i];
-      PangoMapEntry *entry = submap->is_leaf ? &submap->d.entry : &submap->d.leaves[wc % 256];
+      PangoMapEntry *entry = &submap->d.entry;
       
       if (entry->info)
 	return pango_engine_pair_get_engine ((PangoEnginePair *)entry->info);
