Index: glossary.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/glossary/glossary.module,v
retrieving revision 1.100.2.6
diff -u -r1.100.2.6 glossary.module
--- glossary.module	18 Jan 2008 15:39:03 -0000	1.100.2.6
+++ glossary.module	23 Jan 2008 18:09:28 -0000
@@ -568,8 +568,14 @@
  *         $before . $this_match - for checking stuff
  */
 function _glossary_insertlink($format, &$text, $match, $ins_before, $ins_after) {
-
-  $findfunc = (variable_get("glossary_case_$format", "1") ? 'strpos' : 'stripos');
+  $multibyte_enabled = extension_loaded('mbstring');
+	if ($multibyte_enabled) {
+	  $mb_prefix = 'mb_';
+	}
+	else {
+	  $mb_prefix = null;
+	}
+  $findfunc = $mb_prefix . (variable_get("glossary_case_$format", "1") ? 'strpos' : 'stripos');
   $next = $findfunc($text, $match);
   
   if ($next === false) { // no match at all
@@ -578,37 +584,44 @@
   else { // at least one match
     $prevend    = 0;
     $newtext    = '';
-    $matchlen   = strlen($match);
-    $textlen    = strlen($text);
+    $matchlen   = drupal_strlen($match);
+    $textlen    = drupal_strlen($text);
     $replaceall = variable_get("glossary_replace_all_$format", 0);
     
     while ($next && ($next <= $textlen)) {
       
       // get parts of the match for further investigation
-      $before     = substr($text, 0, $next);
-      $this_match = substr($text, $next, $matchlen);
+      $before     = drupal_substr($text, 0, $next);
+      $this_match = drupal_substr($text, $next, $matchlen);
       
       // see if we have a proper match or not
-      $open  = substr_count($before, '<');
-      $close = substr_count($before, '>');
-      $opena  = substr_count($before, '<a ');
-      $closea = substr_count($before, '</a>');
-      $openacro  = substr_count($before, '<acronym');
-      $closeacro = substr_count($before, '</acronym>');
+      $substr_count_func = $mb_prefix . 'substr_count';
+      $open  = $substr_count_func($before, '<');
+      $close = $substr_count_func($before, '>');
+      $opena  = $substr_count_func($before, '<a ');
+      $closea = $substr_count_func($before, '</a>');
+      $openacro  = $substr_count_func($before, '<acronym');
+      $closeacro = $substr_count_func($before, '</acronym>');
       $proper_match = false;
       if ($opena <= $closea && $open <= $close && $openacro <= $closeacro) { // Not in an open link
         switch (variable_get("glossary_match_$format", 'b')) {
           case 'lr': // require word break left or right
-            $proper_match = (_glossary_is_boundary($text {$next - 1}) || _glossary_is_boundary($text {$next + $matchlen}));
+//            $proper_match = (_glossary_is_boundary($text {$next - 1}) || _glossary_is_boundary($text {$next + $matchlen}));
+            $proper_match = (_glossary_is_boundary(drupal_substr($text, $next - 1,1)) ||
+                             _glossary_is_boundary(drupal_substr($text, $next + $matchlen, 1 )));
             break;
           case 'b': // require word break left and right
-            $proper_match = (_glossary_is_boundary($text {$next - 1}) && _glossary_is_boundary($text {$next + $matchlen}));
+//            $proper_match = (_glossary_is_boundary($text {$next - 1}) && _glossary_is_boundary($text {$next + $matchlen}));
+            $proper_match = (_glossary_is_boundary(drupal_substr($text, $next - 1, 1)) &&
+                             _glossary_is_boundary(drupal_substr($text,$next + $matchlen,1)));
             break;
           case 'l':  // require word break left
-            $proper_match = _glossary_is_boundary($text {$next - 1});
+//            $proper_match = _glossary_is_boundary($text {$next - 1});
+            $proper_match = _glossary_is_boundary(drupal_substr($text,$next - 1,1));
             break;
           case 'r': // require word break right
-            $proper_match = _glossary_is_boundary($text {$next + $matchlen});
+//            $proper_match = _glossary_is_boundary($text {$next + $matchlen});
+            $proper_match = _glossary_is_boundary(drupal_substr($text,$next + $matchlen,1));
             break;
           case 's': // match any substring
           default:
@@ -618,13 +631,13 @@
       }
       
       if ($proper_match) { // found match
-        $newtext .= substr($text, $prevend, ($next - $prevend)) . $ins_before . $this_match . $ins_after;
+        $newtext .= drupal_substr($text, $prevend, ($next - $prevend)) . $ins_before . $this_match . $ins_after;
         if ($replaceall == 0) { 
-          return $newtext . substr($text, $next + $matchlen); 
+          return $newtext . drupal_substr($text, $next + $matchlen); 
         }
       }
       else { // not applicable match
-        $newtext .= substr($text, $prevend, ($next - $prevend)) . $this_match;
+        $newtext .= drupal_substr($text, $prevend, ($next - $prevend)) . $this_match;
       }
       
       // Step further in finding the next match
@@ -632,7 +645,7 @@
       $next = $findfunc($text, $match, $prevend);
     }
     // Append remaining part
-    return $newtext . substr($text, $prevend);
+    return $newtext . drupal_substr($text, $prevend);
   }
 }
 
@@ -702,7 +715,21 @@
 
   $output = '<div class="glossary-links">';   
   $letters = array_keys($found_letters);
-  sort($letters, SORT_STRING);
+//  sort($letters, SORT_STRING);
+  // This requires extending i18n_languages array in your settings.php. Example:  
+  //  $conf['i18n_languages']['locales'] = array (
+  //                         "pt-br" => "pt_BR.UTF8",
+  //                         "fr" => "fr_FR.UTF8",
+  //                         "en" => "en_US.UTF8",
+  //                         "es" => "es_LA.UTF8");
+  //
+  if (!isset($GLOBALS['conf']['i18n_languages']['locales'])) {  
+      setlocale(LC_ALL,$GLOBALS['conf']['i18n_languages']['locales'][$GLOBALS['locale']]); 
+      usort($letters,'strcoll');
+  }
+	else { 
+      sort($letters);
+  }
   $href = "glossary/$vid";
   foreach ($letters as $letter) {
     $letter_link = 'letter'. $letter;
@@ -873,14 +900,24 @@
 // the ereg solution used before. The chars used here are from the
 // grep info page.
 function _glossary_is_boundary($char) {
-  return (strpos("!\"#\$%&'()*+,-./:;<=>?@[\]^_`{|}~ \t\n\r", $char) !== false);
+	if (extension_loaded('mbstring')) {
+    return (mb_strpos("!\"#\$%&'()*+,-./:;<=>?@[\]^_`{|}~ \t\n\r", $char) !== false);
+	}
+	else {
+    return (strpos("!\"#\$%&'()*+,-./:;<=>?@[\]^_`{|}~ \t\n\r", $char) !== false);
+	}
 }
 
 // Natively only available in PHP 5+
 // WARNING: Eats a tremendous amount of memory!
 if (!function_exists("stripos")) {
   function stripos($haystack, $needle, $offset = 0) {
-    return strpos(strtoupper($haystack), strtoupper($needle), $offset);
+    return strpos(drupal_strtoupper($haystack), drupal_strtoupper($needle), $offset);
+  }
+}
+if (!function_exists("mb_stripos")) {
+  function mb_stripos($haystack, $needle, $offset = 0) {
+    return mb_strpos(drupal_strtoupper($haystack), drupal_strtoupper($needle), $offset);
   }
 }
 
