diff options
Diffstat (limited to 'lib/win32/glib-2.20.4/glib/gunicollate.c')
-rw-r--r-- | lib/win32/glib-2.20.4/glib/gunicollate.c | 679 |
1 files changed, 0 insertions, 679 deletions
diff --git a/lib/win32/glib-2.20.4/glib/gunicollate.c b/lib/win32/glib-2.20.4/glib/gunicollate.c deleted file mode 100644 index 2bf579ecae..0000000000 --- a/lib/win32/glib-2.20.4/glib/gunicollate.c +++ /dev/null @@ -1,679 +0,0 @@ -/* gunicollate.c - Collation - * - * Copyright 2001,2005 Red Hat, Inc. - * - * The Gnome Library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * The Gnome Library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the Gnome Library; see the file COPYING.LIB. If not, - * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#include "config.h" - -#include <locale.h> -#include <string.h> -#ifdef __STDC_ISO_10646__ -#include <wchar.h> -#endif - -#ifdef HAVE_CARBON -#include <CoreServices/CoreServices.h> -#endif - -#include "glib.h" -#include "gunicodeprivate.h" -#include "galias.h" - -#ifdef _MSC_VER -/* Workaround for bug in MSVCR80.DLL */ -static gsize -msc_strxfrm_wrapper (char *string1, - const char *string2, - gsize count) -{ - if (!string1 || count <= 0) - { - char tmp; - - return strxfrm (&tmp, string2, 1); - } - return strxfrm (string1, string2, count); -} -#define strxfrm msc_strxfrm_wrapper -#endif - -/** - * g_utf8_collate: - * @str1: a UTF-8 encoded string - * @str2: a UTF-8 encoded string - * - * Compares two strings for ordering using the linguistically - * correct rules for the <link linkend="setlocale">current locale</link>. - * When sorting a large number of strings, it will be significantly - * faster to obtain collation keys with g_utf8_collate_key() and - * compare the keys with strcmp() when sorting instead of sorting - * the original strings. - * - * Return value: < 0 if @str1 compares before @str2, - * 0 if they compare equal, > 0 if @str1 compares after @str2. - **/ -gint -g_utf8_collate (const gchar *str1, - const gchar *str2) -{ - gint result; - -#ifdef HAVE_CARBON - - UniChar *str1_utf16; - UniChar *str2_utf16; - glong len1; - glong len2; - SInt32 retval = 0; - - g_return_val_if_fail (str1 != NULL, 0); - g_return_val_if_fail (str2 != NULL, 0); - - str1_utf16 = g_utf8_to_utf16 (str1, -1, NULL, &len1, NULL); - str2_utf16 = g_utf8_to_utf16 (str2, -1, NULL, &len2, NULL); - - UCCompareTextDefault (kUCCollateStandardOptions, - str1_utf16, len1, str2_utf16, len2, - NULL, &retval); - result = retval; - - g_free (str2_utf16); - g_free (str1_utf16); - -#elif defined(__STDC_ISO_10646__) - - gunichar *str1_norm; - gunichar *str2_norm; - - g_return_val_if_fail (str1 != NULL, 0); - g_return_val_if_fail (str2 != NULL, 0); - - str1_norm = _g_utf8_normalize_wc (str1, -1, G_NORMALIZE_ALL_COMPOSE); - str2_norm = _g_utf8_normalize_wc (str2, -1, G_NORMALIZE_ALL_COMPOSE); - - result = wcscoll ((wchar_t *)str1_norm, (wchar_t *)str2_norm); - - g_free (str1_norm); - g_free (str2_norm); - -#else /* !__STDC_ISO_10646__ */ - - const gchar *charset; - gchar *str1_norm; - gchar *str2_norm; - - g_return_val_if_fail (str1 != NULL, 0); - g_return_val_if_fail (str2 != NULL, 0); - - str1_norm = g_utf8_normalize (str1, -1, G_NORMALIZE_ALL_COMPOSE); - str2_norm = g_utf8_normalize (str2, -1, G_NORMALIZE_ALL_COMPOSE); - - if (g_get_charset (&charset)) - { - result = strcoll (str1_norm, str2_norm); - } - else - { - gchar *str1_locale = g_convert (str1_norm, -1, charset, "UTF-8", NULL, NULL, NULL); - gchar *str2_locale = g_convert (str2_norm, -1, charset, "UTF-8", NULL, NULL, NULL); - - if (str1_locale && str2_locale) - result = strcoll (str1_locale, str2_locale); - else if (str1_locale) - result = -1; - else if (str2_locale) - result = 1; - else - result = strcmp (str1_norm, str2_norm); - - g_free (str1_locale); - g_free (str2_locale); - } - - g_free (str1_norm); - g_free (str2_norm); - -#endif /* __STDC_ISO_10646__ */ - - return result; -} - -#if defined(__STDC_ISO_10646__) || defined(HAVE_CARBON) -/* We need UTF-8 encoding of numbers to encode the weights if - * we are using wcsxfrm. However, we aren't encoding Unicode - * characters, so we can't simply use g_unichar_to_utf8. - * - * The following routine is taken (with modification) from GNU - * libc's strxfrm routine: - * - * Copyright (C) 1995-1999,2000,2001 Free Software Foundation, Inc. - * Written by Ulrich Drepper <drepper@cygnus.com>, 1995. - */ -static inline int -utf8_encode (char *buf, wchar_t val) -{ - int retval; - - if (val < 0x80) - { - if (buf) - *buf++ = (char) val; - retval = 1; - } - else - { - int step; - - for (step = 2; step < 6; ++step) - if ((val & (~(guint32)0 << (5 * step + 1))) == 0) - break; - retval = step; - - if (buf) - { - *buf = (unsigned char) (~0xff >> step); - --step; - do - { - buf[step] = 0x80 | (val & 0x3f); - val >>= 6; - } - while (--step > 0); - *buf |= val; - } - } - - return retval; -} -#endif /* __STDC_ISO_10646__ || HAVE_CARBON */ - -#ifdef HAVE_CARBON - -static gchar * -collate_key_to_string (UCCollationValue *key, - gsize key_len) -{ - gchar *result; - gsize result_len; - gsize i; - - /* Pretty smart algorithm here: ignore first eight bytes of the - * collation key. It doesn't produce results equivalent to - * UCCompareCollationKeys's, but the difference seems to be only - * that UCCompareCollationKeys in some cases produces 0 where our - * comparison gets -1 or 1. */ - - if (key_len * sizeof (UCCollationValue) <= 8) - return g_strdup (""); - - result_len = 0; - for (i = 8; i < key_len * sizeof (UCCollationValue); i++) - /* there may be nul bytes, encode byteval+1 */ - result_len += utf8_encode (NULL, *((guchar*)key + i) + 1); - - result = g_malloc (result_len + 1); - result_len = 0; - for (i = 8; i < key_len * sizeof (UCCollationValue); i++) - result_len += utf8_encode (result + result_len, *((guchar*)key + i) + 1); - - result[result_len] = 0; - return result; -} - -static gchar * -carbon_collate_key_with_collator (const gchar *str, - gssize len, - CollatorRef collator) -{ - UniChar *str_utf16 = NULL; - glong len_utf16; - OSStatus ret; - UCCollationValue staticbuf[512]; - UCCollationValue *freeme = NULL; - UCCollationValue *buf; - ItemCount buf_len; - ItemCount key_len; - ItemCount try_len; - gchar *result = NULL; - - str_utf16 = g_utf8_to_utf16 (str, len, NULL, &len_utf16, NULL); - try_len = len_utf16 * 5 + 2; - - if (try_len <= sizeof staticbuf) - { - buf = staticbuf; - buf_len = sizeof staticbuf; - } - else - { - freeme = g_new (UCCollationValue, try_len); - buf = freeme; - buf_len = try_len; - } - - ret = UCGetCollationKey (collator, str_utf16, len_utf16, - buf_len, &key_len, buf); - - if (ret == kCollateBufferTooSmall) - { - freeme = g_renew (UCCollationValue, freeme, try_len * 2); - buf = freeme; - buf_len = try_len * 2; - ret = UCGetCollationKey (collator, str_utf16, len_utf16, - buf_len, &key_len, buf); - } - - if (ret == 0) - result = collate_key_to_string (buf, key_len); - else - result = g_strdup (""); - - g_free (freeme); - g_free (str_utf16); - return result; -} - -static gchar * -carbon_collate_key (const gchar *str, - gssize len) -{ - static CollatorRef collator; - - if (G_UNLIKELY (!collator)) - { - UCCreateCollator (NULL, 0, kUCCollateStandardOptions, &collator); - - if (!collator) - { - static gboolean been_here; - if (!been_here) - g_warning ("%s: UCCreateCollator failed", G_STRLOC); - been_here = TRUE; - return g_strdup (""); - } - } - - return carbon_collate_key_with_collator (str, len, collator); -} - -static gchar * -carbon_collate_key_for_filename (const gchar *str, - gssize len) -{ - static CollatorRef collator; - - if (G_UNLIKELY (!collator)) - { - /* http://developer.apple.com/qa/qa2004/qa1159.html */ - UCCreateCollator (NULL, 0, - kUCCollateComposeInsensitiveMask - | kUCCollateWidthInsensitiveMask - | kUCCollateCaseInsensitiveMask - | kUCCollateDigitsOverrideMask - | kUCCollateDigitsAsNumberMask - | kUCCollatePunctuationSignificantMask, - &collator); - - if (!collator) - { - static gboolean been_here; - if (!been_here) - g_warning ("%s: UCCreateCollator failed", G_STRLOC); - been_here = TRUE; - return g_strdup (""); - } - } - - return carbon_collate_key_with_collator (str, len, collator); -} - -#endif /* HAVE_CARBON */ - -/** - * g_utf8_collate_key: - * @str: a UTF-8 encoded string. - * @len: length of @str, in bytes, or -1 if @str is nul-terminated. - * - * Converts a string into a collation key that can be compared - * with other collation keys produced by the same function using - * strcmp(). - * - * The results of comparing the collation keys of two strings - * with strcmp() will always be the same as comparing the two - * original keys with g_utf8_collate(). - * - * Note that this function depends on the - * <link linkend="setlocale">current locale</link>. - * - * Return value: a newly allocated string. This string should - * be freed with g_free() when you are done with it. - **/ -gchar * -g_utf8_collate_key (const gchar *str, - gssize len) -{ - gchar *result; - -#ifdef HAVE_CARBON - - g_return_val_if_fail (str != NULL, NULL); - result = carbon_collate_key (str, len); - -#elif defined(__STDC_ISO_10646__) - - gsize xfrm_len; - gunichar *str_norm; - wchar_t *result_wc; - gsize i; - gsize result_len = 0; - - g_return_val_if_fail (str != NULL, NULL); - - str_norm = _g_utf8_normalize_wc (str, len, G_NORMALIZE_ALL_COMPOSE); - - xfrm_len = wcsxfrm (NULL, (wchar_t *)str_norm, 0); - result_wc = g_new (wchar_t, xfrm_len + 1); - wcsxfrm (result_wc, (wchar_t *)str_norm, xfrm_len + 1); - - for (i=0; i < xfrm_len; i++) - result_len += utf8_encode (NULL, result_wc[i]); - - result = g_malloc (result_len + 1); - result_len = 0; - for (i=0; i < xfrm_len; i++) - result_len += utf8_encode (result + result_len, result_wc[i]); - - result[result_len] = '\0'; - - g_free (result_wc); - g_free (str_norm); - - return result; -#else /* !__STDC_ISO_10646__ */ - - gsize xfrm_len; - const gchar *charset; - gchar *str_norm; - - g_return_val_if_fail (str != NULL, NULL); - - str_norm = g_utf8_normalize (str, len, G_NORMALIZE_ALL_COMPOSE); - - result = NULL; - - if (g_get_charset (&charset)) - { - xfrm_len = strxfrm (NULL, str_norm, 0); - if (xfrm_len >= 0 && xfrm_len < G_MAXINT - 2) - { - result = g_malloc (xfrm_len + 1); - strxfrm (result, str_norm, xfrm_len + 1); - } - } - else - { - gchar *str_locale = g_convert (str_norm, -1, charset, "UTF-8", NULL, NULL, NULL); - - if (str_locale) - { - xfrm_len = strxfrm (NULL, str_locale, 0); - if (xfrm_len < 0 || xfrm_len >= G_MAXINT - 2) - { - g_free (str_locale); - str_locale = NULL; - } - } - if (str_locale) - { - result = g_malloc (xfrm_len + 2); - result[0] = 'A'; - strxfrm (result + 1, str_locale, xfrm_len + 1); - - g_free (str_locale); - } - } - - if (!result) - { - xfrm_len = strlen (str_norm); - result = g_malloc (xfrm_len + 2); - result[0] = 'B'; - memcpy (result + 1, str_norm, xfrm_len); - result[xfrm_len+1] = '\0'; - } - - g_free (str_norm); -#endif /* __STDC_ISO_10646__ */ - - return result; -} - -/* This is a collation key that is very very likely to sort before any - collation key that libc strxfrm generates. We use this before any - special case (dot or number) to make sure that its sorted before - anything else. - */ -#define COLLATION_SENTINEL "\1\1\1" - -/** - * g_utf8_collate_key_for_filename: - * @str: a UTF-8 encoded string. - * @len: length of @str, in bytes, or -1 if @str is nul-terminated. - * - * Converts a string into a collation key that can be compared - * with other collation keys produced by the same function using strcmp(). - * - * In order to sort filenames correctly, this function treats the dot '.' - * as a special case. Most dictionary orderings seem to consider it - * insignificant, thus producing the ordering "event.c" "eventgenerator.c" - * "event.h" instead of "event.c" "event.h" "eventgenerator.c". Also, we - * would like to treat numbers intelligently so that "file1" "file10" "file5" - * is sorted as "file1" "file5" "file10". - * - * Note that this function depends on the - * <link linkend="setlocale">current locale</link>. - * - * Return value: a newly allocated string. This string should - * be freed with g_free() when you are done with it. - * - * Since: 2.8 - */ -gchar* -g_utf8_collate_key_for_filename (const gchar *str, - gssize len) -{ -#ifndef HAVE_CARBON - GString *result; - GString *append; - const gchar *p; - const gchar *prev; - const gchar *end; - gchar *collate_key; - gint digits; - gint leading_zeros; - - /* - * How it works: - * - * Split the filename into collatable substrings which do - * not contain [.0-9] and special-cased substrings. The collatable - * substrings are run through the normal g_utf8_collate_key() and the - * resulting keys are concatenated with keys generated from the - * special-cased substrings. - * - * Special cases: Dots are handled by replacing them with '\1' which - * implies that short dot-delimited substrings are before long ones, - * e.g. - * - * a\1a (a.a) - * a-\1a (a-.a) - * aa\1a (aa.a) - * - * Numbers are handled by prepending to each number d-1 superdigits - * where d = number of digits in the number and SUPERDIGIT is a - * character with an integer value higher than any digit (for instance - * ':'). This ensures that single-digit numbers are sorted before - * double-digit numbers which in turn are sorted separately from - * triple-digit numbers, etc. To avoid strange side-effects when - * sorting strings that already contain SUPERDIGITs, a '\2' - * is also prepended, like this - * - * file\21 (file1) - * file\25 (file5) - * file\2:10 (file10) - * file\2:26 (file26) - * file\2::100 (file100) - * file:foo (file:foo) - * - * This has the side-effect of sorting numbers before everything else (except - * dots), but this is probably OK. - * - * Leading digits are ignored when doing the above. To discriminate - * numbers which differ only in the number of leading digits, we append - * the number of leading digits as a byte at the very end of the collation - * key. - * - * To try avoid conflict with any collation key sequence generated by libc we - * start each switch to a special cased part with a sentinel that hopefully - * will sort before anything libc will generate. - */ - - if (len < 0) - len = strlen (str); - - result = g_string_sized_new (len * 2); - append = g_string_sized_new (0); - - end = str + len; - - /* No need to use utf8 functions, since we're only looking for ascii chars */ - for (prev = p = str; p < end; p++) - { - switch (*p) - { - case '.': - if (prev != p) - { - collate_key = g_utf8_collate_key (prev, p - prev); - g_string_append (result, collate_key); - g_free (collate_key); - } - - g_string_append (result, COLLATION_SENTINEL "\1"); - - /* skip the dot */ - prev = p + 1; - break; - - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - if (prev != p) - { - collate_key = g_utf8_collate_key (prev, p - prev); - g_string_append (result, collate_key); - g_free (collate_key); - } - - g_string_append (result, COLLATION_SENTINEL "\2"); - - prev = p; - - /* write d-1 colons */ - if (*p == '0') - { - leading_zeros = 1; - digits = 0; - } - else - { - leading_zeros = 0; - digits = 1; - } - - while (++p < end) - { - if (*p == '0' && !digits) - ++leading_zeros; - else if (g_ascii_isdigit(*p)) - ++digits; - else - { - /* count an all-zero sequence as - * one digit plus leading zeros - */ - if (!digits) - { - ++digits; - --leading_zeros; - } - break; - } - } - - while (digits > 1) - { - g_string_append_c (result, ':'); - --digits; - } - - if (leading_zeros > 0) - { - g_string_append_c (append, (char)leading_zeros); - prev += leading_zeros; - } - - /* write the number itself */ - g_string_append_len (result, prev, p - prev); - - prev = p; - --p; /* go one step back to avoid disturbing outer loop */ - break; - - default: - /* other characters just accumulate */ - break; - } - } - - if (prev != p) - { - collate_key = g_utf8_collate_key (prev, p - prev); - g_string_append (result, collate_key); - g_free (collate_key); - } - - g_string_append (result, append->str); - g_string_free (append, TRUE); - - return g_string_free (result, FALSE); -#else /* HAVE_CARBON */ - return carbon_collate_key_for_filename (str, len); -#endif -} - - -#define __G_UNICOLLATE_C__ -#include "galiasdef.c" |