diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 11 | ||||
| -rw-r--r-- | src/fns.c | 54 | ||||
| -rw-r--r-- | src/lisp.h | 2 | ||||
| -rw-r--r-- | src/sysdep.c | 80 |
4 files changed, 110 insertions, 37 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index b3c056edd07..66588bc3e67 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,3 +1,14 @@ | |||
| 1 | 2014-08-29 Michael Albinus <michael.albinus@gmx.de> | ||
| 2 | |||
| 3 | * sysdep.c (LC_CTYPE, LC_CTYPE_MASK, towlower_l): | ||
| 4 | Define substitutes for platforms that lack them. | ||
| 5 | (str_collate): Add arguments locale and ignore_case. | ||
| 6 | |||
| 7 | * fns.c (Fstring_collate_lessp, Fstring_collate_equalp): | ||
| 8 | Add optional arguments LOCALE and IGNORE-CASE. | ||
| 9 | |||
| 10 | * lisp.h (str_collate): Adapt argument list. | ||
| 11 | |||
| 1 | 2014-08-29 Dmitry Antipov <dmantipov@yandex.ru> | 12 | 2014-08-29 Dmitry Antipov <dmantipov@yandex.ru> |
| 2 | 13 | ||
| 3 | Add vectors support to Fsort. | 14 | Add vectors support to Fsort. |
| @@ -344,25 +344,28 @@ Symbols are also allowed; their print names are used instead. */) | |||
| 344 | return i1 < SCHARS (s2) ? Qt : Qnil; | 344 | return i1 < SCHARS (s2) ? Qt : Qnil; |
| 345 | } | 345 | } |
| 346 | 346 | ||
| 347 | DEFUN ("string-collate-lessp", Fstring_collate_lessp, Sstring_collate_lessp, 2, 2, 0, | 347 | DEFUN ("string-collate-lessp", Fstring_collate_lessp, Sstring_collate_lessp, 2, 4, 0, |
| 348 | doc: /* Return t if first arg string is less than second in collation order. | 348 | doc: /* Return t if first arg string is less than second in collation order. |
| 349 | 349 | Symbols are also allowed; their print names are used instead. | |
| 350 | Case is significant. Symbols are also allowed; their print names are | ||
| 351 | used instead. | ||
| 352 | 350 | ||
| 353 | This function obeys the conventions for collation order in your | 351 | This function obeys the conventions for collation order in your |
| 354 | locale settings. For example, punctuation and whitespace characters | 352 | locale settings. For example, punctuation and whitespace characters |
| 355 | are considered less significant for sorting. | 353 | are considered less significant for sorting: |
| 356 | 354 | ||
| 357 | \(sort '\("11" "12" "1 1" "1 2" "1.1" "1.2") 'string-collate-lessp) | 355 | \(sort '\("11" "12" "1 1" "1 2" "1.1" "1.2") 'string-collate-lessp) |
| 358 | => \("11" "1 1" "1.1" "12" "1 2" "1.2") | 356 | => \("11" "1 1" "1.1" "12" "1 2" "1.2") |
| 359 | 357 | ||
| 360 | If your system does not support a locale environment, this function | 358 | The optional argument LOCALE, a string, overrides the setting of your |
| 361 | behaves like `string-lessp'. | 359 | current locale identifier for collation. The value is system |
| 360 | dependent; a LOCALE \"en_US.UTF-8\" is applicable on POSIX systems, | ||
| 361 | while it would be \"English_USA.1252\" on MS Windows systems. | ||
| 362 | 362 | ||
| 363 | If the environment variable \"LC_COLLATE\" is set in `process-environment', | 363 | If IGNORE-CASE is non-nil, characters are converted to lower-case |
| 364 | it overrides the setting of your current locale. */) | 364 | before comparing them. |
| 365 | (Lisp_Object s1, Lisp_Object s2) | 365 | |
| 366 | If your system does not support a locale environment, this function | ||
| 367 | behaves like `string-lessp'. */) | ||
| 368 | (Lisp_Object s1, Lisp_Object s2, Lisp_Object locale, Lisp_Object ignore_case) | ||
| 366 | { | 369 | { |
| 367 | #if defined __STDC_ISO_10646__ || defined WINDOWSNT | 370 | #if defined __STDC_ISO_10646__ || defined WINDOWSNT |
| 368 | /* Check parameters. */ | 371 | /* Check parameters. */ |
| @@ -372,34 +375,39 @@ it overrides the setting of your current locale. */) | |||
| 372 | s2 = SYMBOL_NAME (s2); | 375 | s2 = SYMBOL_NAME (s2); |
| 373 | CHECK_STRING (s1); | 376 | CHECK_STRING (s1); |
| 374 | CHECK_STRING (s2); | 377 | CHECK_STRING (s2); |
| 378 | if (!NILP (locale)) | ||
| 379 | CHECK_STRING (locale); | ||
| 375 | 380 | ||
| 376 | return (str_collate (s1, s2) < 0) ? Qt : Qnil; | 381 | return (str_collate (s1, s2, locale, ignore_case) < 0) ? Qt : Qnil; |
| 377 | 382 | ||
| 378 | #else /* !__STDC_ISO_10646__, !WINDOWSNT */ | 383 | #else /* !__STDC_ISO_10646__, !WINDOWSNT */ |
| 379 | return Fstring_lessp (s1, s2); | 384 | return Fstring_lessp (s1, s2); |
| 380 | #endif /* !__STDC_ISO_10646__, !WINDOWSNT */ | 385 | #endif /* !__STDC_ISO_10646__, !WINDOWSNT */ |
| 381 | } | 386 | } |
| 382 | 387 | ||
| 383 | DEFUN ("string-collate-equalp", Fstring_collate_equalp, Sstring_collate_equalp, 2, 2, 0, | 388 | DEFUN ("string-collate-equalp", Fstring_collate_equalp, Sstring_collate_equalp, 2, 4, 0, |
| 384 | doc: /* Return t if two strings have identical contents. | 389 | doc: /* Return t if two strings have identical contents. |
| 385 | 390 | Symbols are also allowed; their print names are used instead. | |
| 386 | Case is significant. Symbols are also allowed; their print names are | ||
| 387 | used instead. | ||
| 388 | 391 | ||
| 389 | This function obeys the conventions for collation order in your locale | 392 | This function obeys the conventions for collation order in your locale |
| 390 | settings. For example, characters with different coding points but | 393 | settings. For example, characters with different coding points but |
| 391 | the same meaning are considered as equal, like different grave accent | 394 | the same meaning are considered as equal, like different grave accent |
| 392 | unicode characters. | 395 | unicode characters: |
| 393 | 396 | ||
| 394 | \(string-collate-equalp \(string ?\\uFF40) \(string ?\\u1FEF)) | 397 | \(string-collate-equalp \(string ?\\uFF40) \(string ?\\u1FEF)) |
| 395 | => t | 398 | => t |
| 396 | 399 | ||
| 397 | If your system does not support a locale environment, this function | 400 | The optional argument LOCALE, a string, overrides the setting of your |
| 398 | behaves like `string-equal'. | 401 | current locale identifier for collation. The value is system |
| 402 | dependent; a LOCALE \"en_US.UTF-8\" is applicable on POSIX systems, | ||
| 403 | while it would be \"English_USA.1252\" on MS Windows systems. | ||
| 399 | 404 | ||
| 400 | If the environment variable \"LC_COLLATE\" is set in `process-environment', | 405 | If IGNORE-CASE is non-nil, characters are converted to lower-case |
| 401 | it overrides the setting of your current locale. */) | 406 | before comparing them. |
| 402 | (Lisp_Object s1, Lisp_Object s2) | 407 | |
| 408 | If your system does not support a locale environment, this function | ||
| 409 | behaves like `string-equal'. */) | ||
| 410 | (Lisp_Object s1, Lisp_Object s2, Lisp_Object locale, Lisp_Object ignore_case) | ||
| 403 | { | 411 | { |
| 404 | #if defined __STDC_ISO_10646__ || defined WINDOWSNT | 412 | #if defined __STDC_ISO_10646__ || defined WINDOWSNT |
| 405 | /* Check parameters. */ | 413 | /* Check parameters. */ |
| @@ -409,8 +417,10 @@ it overrides the setting of your current locale. */) | |||
| 409 | s2 = SYMBOL_NAME (s2); | 417 | s2 = SYMBOL_NAME (s2); |
| 410 | CHECK_STRING (s1); | 418 | CHECK_STRING (s1); |
| 411 | CHECK_STRING (s2); | 419 | CHECK_STRING (s2); |
| 420 | if (!NILP (locale)) | ||
| 421 | CHECK_STRING (locale); | ||
| 412 | 422 | ||
| 413 | return (str_collate (s1, s2) == 0) ? Qt : Qnil; | 423 | return (str_collate (s1, s2, locale, ignore_case) == 0) ? Qt : Qnil; |
| 414 | 424 | ||
| 415 | #else /* !__STDC_ISO_10646__, !WINDOWSNT */ | 425 | #else /* !__STDC_ISO_10646__, !WINDOWSNT */ |
| 416 | return Fstring_equal (s1, s2); | 426 | return Fstring_equal (s1, s2); |
diff --git a/src/lisp.h b/src/lisp.h index 7cbbb299896..d31c5ae50c3 100644 --- a/src/lisp.h +++ b/src/lisp.h | |||
| @@ -4301,7 +4301,7 @@ extern void lock_file (Lisp_Object); | |||
| 4301 | extern void unlock_file (Lisp_Object); | 4301 | extern void unlock_file (Lisp_Object); |
| 4302 | extern void unlock_buffer (struct buffer *); | 4302 | extern void unlock_buffer (struct buffer *); |
| 4303 | extern void syms_of_filelock (void); | 4303 | extern void syms_of_filelock (void); |
| 4304 | extern int str_collate (Lisp_Object, Lisp_Object); | 4304 | extern int str_collate (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object); |
| 4305 | 4305 | ||
| 4306 | /* Defined in sound.c. */ | 4306 | /* Defined in sound.c. */ |
| 4307 | extern void syms_of_sound (void); | 4307 | extern void syms_of_sound (void); |
diff --git a/src/sysdep.c b/src/sysdep.c index c753f84831b..a730cb4a8ff 100644 --- a/src/sysdep.c +++ b/src/sysdep.c | |||
| @@ -3605,6 +3605,7 @@ system_process_attributes (Lisp_Object pid) | |||
| 3605 | 3605 | ||
| 3606 | #ifdef __STDC_ISO_10646__ | 3606 | #ifdef __STDC_ISO_10646__ |
| 3607 | # include <wchar.h> | 3607 | # include <wchar.h> |
| 3608 | # include <wctype.h> | ||
| 3608 | 3609 | ||
| 3609 | # if defined HAVE_NEWLOCALE || defined HAVE_SETLOCALE | 3610 | # if defined HAVE_NEWLOCALE || defined HAVE_SETLOCALE |
| 3610 | # include <locale.h> | 3611 | # include <locale.h> |
| @@ -3615,15 +3616,24 @@ system_process_attributes (Lisp_Object pid) | |||
| 3615 | # ifndef LC_COLLATE_MASK | 3616 | # ifndef LC_COLLATE_MASK |
| 3616 | # define LC_COLLATE_MASK 0 | 3617 | # define LC_COLLATE_MASK 0 |
| 3617 | # endif | 3618 | # endif |
| 3619 | # ifndef LC_CTYPE | ||
| 3620 | # define LC_CTYPE 0 | ||
| 3621 | # endif | ||
| 3622 | # ifndef LC_CTYPE_MASK | ||
| 3623 | # define LC_CTYPE_MASK 0 | ||
| 3624 | # endif | ||
| 3625 | |||
| 3618 | # ifndef HAVE_NEWLOCALE | 3626 | # ifndef HAVE_NEWLOCALE |
| 3619 | # undef freelocale | 3627 | # undef freelocale |
| 3620 | # undef locale_t | 3628 | # undef locale_t |
| 3621 | # undef newlocale | 3629 | # undef newlocale |
| 3622 | # undef wcscoll_l | 3630 | # undef wcscoll_l |
| 3631 | # undef towlower_l | ||
| 3623 | # define freelocale emacs_freelocale | 3632 | # define freelocale emacs_freelocale |
| 3624 | # define locale_t emacs_locale_t | 3633 | # define locale_t emacs_locale_t |
| 3625 | # define newlocale emacs_newlocale | 3634 | # define newlocale emacs_newlocale |
| 3626 | # define wcscoll_l emacs_wcscoll_l | 3635 | # define wcscoll_l emacs_wcscoll_l |
| 3636 | # define towlower_l emacs_towlower_l | ||
| 3627 | 3637 | ||
| 3628 | typedef char const *locale_t; | 3638 | typedef char const *locale_t; |
| 3629 | 3639 | ||
| @@ -3683,15 +3693,37 @@ wcscoll_l (wchar_t const *a, wchar_t const *b, locale_t loc) | |||
| 3683 | errno = err; | 3693 | errno = err; |
| 3684 | return result; | 3694 | return result; |
| 3685 | } | 3695 | } |
| 3696 | |||
| 3697 | static wint_t | ||
| 3698 | towlower_l (wint_t wc, locale_t loc) | ||
| 3699 | { | ||
| 3700 | wint_t result = wc; | ||
| 3701 | char *oldloc = emacs_setlocale (LC_CTYPE, NULL); | ||
| 3702 | |||
| 3703 | if (oldloc) | ||
| 3704 | { | ||
| 3705 | USE_SAFE_ALLOCA; | ||
| 3706 | char *oldcopy = SAFE_ALLOCA (strlen (oldloc) + 1); | ||
| 3707 | strcpy (oldcopy, oldloc); | ||
| 3708 | if (emacs_setlocale (LC_CTYPE, loc)) | ||
| 3709 | { | ||
| 3710 | result = towlower (wc); | ||
| 3711 | emacs_setlocale (LC_COLLATE, oldcopy); | ||
| 3712 | } | ||
| 3713 | SAFE_FREE (); | ||
| 3714 | } | ||
| 3715 | |||
| 3716 | return result; | ||
| 3717 | } | ||
| 3686 | # endif | 3718 | # endif |
| 3687 | 3719 | ||
| 3688 | int | 3720 | int |
| 3689 | str_collate (Lisp_Object s1, Lisp_Object s2) | 3721 | str_collate (Lisp_Object s1, Lisp_Object s2, |
| 3722 | Lisp_Object locale, Lisp_Object ignore_case) | ||
| 3690 | { | 3723 | { |
| 3691 | int res, err; | 3724 | int res, err; |
| 3692 | ptrdiff_t len, i, i_byte; | 3725 | ptrdiff_t len, i, i_byte; |
| 3693 | wchar_t *p1, *p2; | 3726 | wchar_t *p1, *p2; |
| 3694 | Lisp_Object lc_collate; | ||
| 3695 | 3727 | ||
| 3696 | USE_SAFE_ALLOCA; | 3728 | USE_SAFE_ALLOCA; |
| 3697 | 3729 | ||
| @@ -3708,22 +3740,43 @@ str_collate (Lisp_Object s1, Lisp_Object s2) | |||
| 3708 | FETCH_STRING_CHAR_ADVANCE (*(p2+i-1), s2, i, i_byte); | 3740 | FETCH_STRING_CHAR_ADVANCE (*(p2+i-1), s2, i, i_byte); |
| 3709 | *(p2+len) = 0; | 3741 | *(p2+len) = 0; |
| 3710 | 3742 | ||
| 3711 | lc_collate = | 3743 | if (STRINGP (locale)) |
| 3712 | Fgetenv_internal (build_string ("LC_COLLATE"), Vprocess_environment); | ||
| 3713 | |||
| 3714 | if (STRINGP (lc_collate)) | ||
| 3715 | { | 3744 | { |
| 3716 | locale_t loc = newlocale (LC_COLLATE_MASK, SSDATA (lc_collate), 0); | 3745 | locale_t loc = newlocale (LC_COLLATE_MASK | LC_CTYPE_MASK, |
| 3746 | SSDATA (locale), 0); | ||
| 3717 | if (!loc) | 3747 | if (!loc) |
| 3718 | error ("Wrong locale: %s", strerror (errno)); | 3748 | error ("Wrong locale: %s", strerror (errno)); |
| 3719 | errno = 0; | 3749 | errno = 0; |
| 3720 | res = wcscoll_l (p1, p2, loc); | 3750 | |
| 3751 | if (! NILP (ignore_case)) | ||
| 3752 | for (int i = 1; i < 3; i++) | ||
| 3753 | { | ||
| 3754 | wchar_t *p = (i == 1) ? p1 : p2; | ||
| 3755 | for (; *p; p++) | ||
| 3756 | { | ||
| 3757 | *p = towlower_l (*p, loc); | ||
| 3758 | if (errno) | ||
| 3759 | break; | ||
| 3760 | } | ||
| 3761 | if (errno) | ||
| 3762 | break; | ||
| 3763 | } | ||
| 3764 | |||
| 3765 | if (! errno) | ||
| 3766 | res = wcscoll_l (p1, p2, loc); | ||
| 3721 | err = errno; | 3767 | err = errno; |
| 3722 | freelocale (loc); | 3768 | freelocale (loc); |
| 3723 | } | 3769 | } |
| 3724 | else | 3770 | else |
| 3725 | { | 3771 | { |
| 3726 | errno = 0; | 3772 | errno = 0; |
| 3773 | if (! NILP (ignore_case)) | ||
| 3774 | for (int i = 1; i < 3; i++) | ||
| 3775 | { | ||
| 3776 | wchar_t *p = (i == 1) ? p1 : p2; | ||
| 3777 | for (; *p; p++) | ||
| 3778 | *p = towlower (*p); | ||
| 3779 | } | ||
| 3727 | res = wcscoll (p1, p2); | 3780 | res = wcscoll (p1, p2); |
| 3728 | err = errno; | 3781 | err = errno; |
| 3729 | } | 3782 | } |
| @@ -3733,15 +3786,14 @@ str_collate (Lisp_Object s1, Lisp_Object s2) | |||
| 3733 | SAFE_FREE (); | 3786 | SAFE_FREE (); |
| 3734 | return res; | 3787 | return res; |
| 3735 | } | 3788 | } |
| 3736 | #endif /* __STDC_ISO_10646__ */ | 3789 | #endif /* __STDC_ISO_10646__ */ |
| 3737 | 3790 | ||
| 3738 | #ifdef WINDOWSNT | 3791 | #ifdef WINDOWSNT |
| 3739 | int | 3792 | int |
| 3740 | str_collate (Lisp_Object s1, Lisp_Object s2) | 3793 | str_collate (Lisp_Object s1, Lisp_Object s2, |
| 3741 | { | 3794 | { Lisp_Object locale, Lisp_Object ignore_case) |
| 3742 | Lisp_Object lc_collate = | 3795 | |
| 3743 | Fgetenv_internal (build_string ("LC_COLLATE"), Vprocess_environment); | 3796 | char *loc = STRINGP (locale) ? SSDATA (locale) : NULL; |
| 3744 | char *loc = STRINGP (lc_collate) ? SSDATA (lc_collate) : NULL; | ||
| 3745 | 3797 | ||
| 3746 | return w32_compare_strings (SDATA (s1), SDATA (s2), loc); | 3798 | return w32_compare_strings (SDATA (s1), SDATA (s2), loc); |
| 3747 | } | 3799 | } |