Update contrib.
     1 /* decomp.c - Character decomposition.
 
     3  *  Copyright (C) 1999, 2000 Tom Tromey
 
     4  *  Copyright 2000 Red Hat, Inc.
 
     5  * Portions copyright (c) 2006-2009 Nokia Corporation.  All rights reserved.
 
     7  * The Gnome Library is free software; you can redistribute it and/or
 
     8  * modify it under the terms of the GNU Lesser General Public License as
 
     9  * published by the Free Software Foundation; either version 2 of the
 
    10  * License, or (at your option) any later version.
 
    12  * The Gnome Library is distributed in the hope that it will be useful,
 
    13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
    14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
    15  * Lesser General Public License for more details.
 
    17  * You should have received a copy of the GNU Lesser General Public
 
    18  * License along with the Gnome Library; see the file COPYING.LIB.  If not,
 
    19  * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 
    20  *   Boston, MA 02111-1307, USA.
 
    28 #include "gunidecomp.h"
 
    30 #include "gunicodeprivate.h"
 
    34 #define CC_PART1(Page, Char) \
 
    35   ((combining_class_table_part1[Page] >= G_UNICODE_MAX_TABLE_INDEX) \
 
    36    ? (combining_class_table_part1[Page] - G_UNICODE_MAX_TABLE_INDEX) \
 
    37    : (cclass_data[combining_class_table_part1[Page]][Char]))
 
    39 #define CC_PART2(Page, Char) \
 
    40   ((combining_class_table_part2[Page] >= G_UNICODE_MAX_TABLE_INDEX) \
 
    41    ? (combining_class_table_part2[Page] - G_UNICODE_MAX_TABLE_INDEX) \
 
    42    : (cclass_data[combining_class_table_part2[Page]][Char]))
 
    44 #define COMBINING_CLASS(Char) \
 
    45   (((Char) <= G_UNICODE_LAST_CHAR_PART1) \
 
    46    ? CC_PART1 ((Char) >> 8, (Char) & 0xff) \
 
    47    : (((Char) >= 0xe0000 && (Char) <= G_UNICODE_LAST_CHAR) \
 
    48       ? CC_PART2 (((Char) - 0xe0000) >> 8, (Char) & 0xff) \
 
    52  * g_unichar_combining_class:
 
    53  * @uc: a Unicode character
 
    55  * Determines the canonical combining class of a Unicode character.
 
    57  * Return value: the combining class of the character
 
    62 g_unichar_combining_class (gunichar uc)
 
    64   return COMBINING_CLASS (uc);
 
    67 /* constants for hangul syllable [de]composition */
 
    75 #define NCount (VCount * TCount)
 
    76 #define SCount (LCount * NCount)
 
    79  * g_unicode_canonical_ordering:
 
    80  * @string: a UCS-4 encoded string.
 
    81  * @len: the maximum length of @string to use.
 
    83  * Computes the canonical ordering of a string in-place.  
 
    84  * This rearranges decomposed characters in the string 
 
    85  * according to their combining classes.  See the Unicode 
 
    86  * manual for more information. 
 
    89 g_unicode_canonical_ordering (gunichar *string,
 
    99       last = COMBINING_CLASS (string[0]);
 
   100       for (i = 0; i < len - 1; ++i)
 
   102 	  int next = COMBINING_CLASS (string[i + 1]);
 
   103 	  if (next != 0 && last > next)
 
   106 	      /* Percolate item leftward through string.  */
 
   107 	      for (j = i + 1; j > 0; --j)
 
   110 		  if (COMBINING_CLASS (string[j - 1]) <= next)
 
   113 		  string[j] = string[j - 1];
 
   117 	      /* We're re-entering the loop looking at the old
 
   126 /* http://www.unicode.org/unicode/reports/tr15/#Hangul
 
   127  * r should be null or have sufficient space. Calling with r == NULL will
 
   128  * only calculate the result_len; however, a buffer with space for three
 
   129  * characters will always be big enough. */
 
   131 decompose_hangul (gunichar s, 
 
   135   gint SIndex = s - SBase;
 
   137   /* not a hangul syllable */
 
   138   if (SIndex < 0 || SIndex >= SCount)
 
   146       gunichar L = LBase + SIndex / NCount;
 
   147       gunichar V = VBase + (SIndex % NCount) / TCount;
 
   148       gunichar T = TBase + SIndex % TCount;
 
   167 /* returns a pointer to a null-terminated UTF-8 string */
 
   169 find_decomposition (gunichar ch,
 
   173   int end = G_N_ELEMENTS (decomp_table);
 
   175   if (ch >= decomp_table[start].ch &&
 
   176       ch <= decomp_table[end - 1].ch)
 
   180 	  int half = (start + end) / 2;
 
   181 	  if (ch == decomp_table[half].ch)
 
   187 		  offset = decomp_table[half].compat_offset;
 
   188 		  if (offset == G_UNICODE_NOT_PRESENT_OFFSET)
 
   189 		    offset = decomp_table[half].canon_offset;
 
   193 		  offset = decomp_table[half].canon_offset;
 
   194 		  if (offset == G_UNICODE_NOT_PRESENT_OFFSET)
 
   198 	      return &(decomp_expansion_string[offset]);
 
   200 	  else if (half == start)
 
   202 	  else if (ch > decomp_table[half].ch)
 
   213  * g_unicode_canonical_decomposition:
 
   214  * @ch: a Unicode character.
 
   215  * @result_len: location to store the length of the return value.
 
   217  * Computes the canonical decomposition of a Unicode character.  
 
   219  * Return value: a newly allocated string of Unicode characters.
 
   220  *   @result_len is set to the resulting length of the string.
 
   223 g_unicode_canonical_decomposition (gunichar ch,
 
   230   /* Hangul syllable */
 
   231   if (ch >= 0xac00 && ch <= 0xd7a3)
 
   233       decompose_hangul (ch, NULL, result_len);
 
   234       r = g_malloc (*result_len * sizeof (gunichar));
 
   235       decompose_hangul (ch, r, result_len);
 
   237   else if ((decomp = find_decomposition (ch, FALSE)) != NULL)
 
   242       *result_len = g_utf8_strlen (decomp, -1);
 
   243       r = g_malloc (*result_len * sizeof (gunichar));
 
   245       for (p = decomp, i = 0; *p != '\0'; p = g_utf8_next_char (p), i++)
 
   246         r[i] = g_utf8_get_char (p);
 
   250       /* Not in our table.  */
 
   251       r = g_malloc (sizeof (gunichar));
 
   256   /* Supposedly following the Unicode 2.1.9 table means that the
 
   257      decompositions come out in canonical order.  I haven't tested
 
   258      this, but we rely on it here.  */
 
   262 /* L,V => LV and LV,T => LVT  */
 
   264 combine_hangul (gunichar a,
 
   268   gint LIndex = a - LBase;
 
   269   gint SIndex = a - SBase;
 
   271   gint VIndex = b - VBase;
 
   272   gint TIndex = b - TBase;
 
   274   if (0 <= LIndex && LIndex < LCount
 
   275       && 0 <= VIndex && VIndex < VCount)
 
   277       *result = SBase + (LIndex * VCount + VIndex) * TCount;
 
   280   else if (0 <= SIndex && SIndex < SCount && (SIndex % TCount) == 0
 
   281            && 0 < TIndex && TIndex < TCount)
 
   283       *result = a + TIndex;
 
   290 #define CI(Page, Char) \
 
   291   ((compose_table[Page] >= G_UNICODE_MAX_TABLE_INDEX) \
 
   292    ? (compose_table[Page] - G_UNICODE_MAX_TABLE_INDEX) \
 
   293    : (compose_data[compose_table[Page]][Char]))
 
   295 #define COMPOSE_INDEX(Char) \
 
   296      (((Char >> 8) > (COMPOSE_TABLE_LAST)) ? 0 : CI((Char) >> 8, (Char) & 0xff))
 
   303   gushort index_a, index_b;
 
   305   if (combine_hangul (a, b, result))
 
   308   index_a = COMPOSE_INDEX(a);
 
   310   if (index_a >= COMPOSE_FIRST_SINGLE_START && index_a < COMPOSE_SECOND_START)
 
   312       if (b == compose_first_single[index_a - COMPOSE_FIRST_SINGLE_START][0])
 
   314 	  *result = compose_first_single[index_a - COMPOSE_FIRST_SINGLE_START][1];
 
   321   index_b = COMPOSE_INDEX(b);
 
   323   if (index_b >= COMPOSE_SECOND_SINGLE_START)
 
   325       if (a == compose_second_single[index_b - COMPOSE_SECOND_SINGLE_START][0])
 
   327 	  *result = compose_second_single[index_b - COMPOSE_SECOND_SINGLE_START][1];
 
   334   if (index_a >= COMPOSE_FIRST_START && index_a < COMPOSE_FIRST_SINGLE_START &&
 
   335       index_b >= COMPOSE_SECOND_START && index_b < COMPOSE_SECOND_SINGLE_START)
 
   337       gunichar res = compose_array[index_a - COMPOSE_FIRST_START][index_b - COMPOSE_SECOND_START];
 
   350 _g_utf8_normalize_wc (const gchar    *str,
 
   358   gboolean do_compat = (mode == G_NORMALIZE_NFKC ||
 
   359 			mode == G_NORMALIZE_NFKD);
 
   360   gboolean do_compose = (mode == G_NORMALIZE_NFC ||
 
   361 			 mode == G_NORMALIZE_NFKC);
 
   365   while ((max_len < 0 || p < str + max_len) && *p)
 
   368       gunichar wc = g_utf8_get_char (p);
 
   370       if (wc >= 0xac00 && wc <= 0xd7a3)
 
   373           decompose_hangul (wc, NULL, &result_len);
 
   378           decomp = find_decomposition (wc, do_compat);
 
   381             n_wc += g_utf8_strlen (decomp, -1);
 
   386       p = g_utf8_next_char (p);
 
   389   wc_buffer = g_new (gunichar, n_wc + 1);
 
   394   while ((max_len < 0 || p < str + max_len) && *p)
 
   396       gunichar wc = g_utf8_get_char (p);
 
   399       gsize old_n_wc = n_wc;
 
   401       if (wc >= 0xac00 && wc <= 0xd7a3)
 
   404           decompose_hangul (wc, wc_buffer + n_wc, &result_len);
 
   409           decomp = find_decomposition (wc, do_compat);
 
   414               for (pd = decomp; *pd != '\0'; pd = g_utf8_next_char (pd))
 
   415                 wc_buffer[n_wc++] = g_utf8_get_char (pd);
 
   418             wc_buffer[n_wc++] = wc;
 
   423 	  cc = COMBINING_CLASS (wc_buffer[old_n_wc]);
 
   427 	      g_unicode_canonical_ordering (wc_buffer + last_start, n_wc - last_start);
 
   428 	      last_start = old_n_wc;
 
   432       p = g_utf8_next_char (p);
 
   437       g_unicode_canonical_ordering (wc_buffer + last_start, n_wc - last_start);
 
   443   /* All decomposed and reordered */ 
 
   445   if (do_compose && n_wc > 0)
 
   451       for (i = 0; i < n_wc; i++)
 
   453 	  int cc = COMBINING_CLASS (wc_buffer[i]);
 
   456 	      (last_cc == 0 || last_cc < cc) &&
 
   457 	      combine (wc_buffer[last_start], wc_buffer[i],
 
   458 		       &wc_buffer[last_start]))
 
   460 	      for (j = i + 1; j < n_wc; j++)
 
   461 		wc_buffer[j-1] = wc_buffer[j];
 
   468 		last_cc = COMBINING_CLASS (wc_buffer[i-1]);
 
   487  * @str: a UTF-8 encoded string.
 
   488  * @len: length of @str, in bytes, or -1 if @str is nul-terminated.
 
   489  * @mode: the type of normalization to perform.
 
   491  * Converts a string into canonical form, standardizing
 
   492  * such issues as whether a character with an accent
 
   493  * is represented as a base character and combining
 
   494  * accent or as a single precomposed character. The
 
   495  * string has to be valid UTF-8, otherwise %NULL is
 
   496  * returned. You should generally call g_utf8_normalize()
 
   497  * before comparing two Unicode strings.
 
   499  * The normalization mode %G_NORMALIZE_DEFAULT only
 
   500  * standardizes differences that do not affect the
 
   501  * text content, such as the above-mentioned accent
 
   502  * representation. %G_NORMALIZE_ALL also standardizes
 
   503  * the "compatibility" characters in Unicode, such
 
   504  * as SUPERSCRIPT THREE to the standard forms
 
   505  * (in this case DIGIT THREE). Formatting information
 
   506  * may be lost but for most text operations such
 
   507  * characters should be considered the same.
 
   509  * %G_NORMALIZE_DEFAULT_COMPOSE and %G_NORMALIZE_ALL_COMPOSE
 
   510  * are like %G_NORMALIZE_DEFAULT and %G_NORMALIZE_ALL,
 
   511  * but returned a result with composed forms rather
 
   512  * than a maximally decomposed form. This is often
 
   513  * useful if you intend to convert the string to
 
   514  * a legacy encoding or pass it to a system with
 
   515  * less capable Unicode handling.
 
   517  * Return value: a newly allocated string, that is the
 
   518  *   normalized form of @str, or %NULL if @str is not
 
   522 g_utf8_normalize (const gchar    *str,
 
   526   gunichar *result_wc = _g_utf8_normalize_wc (str, len, mode);
 
   529   result = g_ucs4_to_utf8 (result_wc, -1, NULL, NULL, NULL);
 
   535 #define __G_UNIDECOMP_C__
 
   536 #include "galiasdef.c"