aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog11
-rw-r--r--src/fns.c54
-rw-r--r--src/lisp.h2
-rw-r--r--src/sysdep.c80
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 @@
12014-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
12014-08-29 Dmitry Antipov <dmantipov@yandex.ru> 122014-08-29 Dmitry Antipov <dmantipov@yandex.ru>
2 13
3 Add vectors support to Fsort. 14 Add vectors support to Fsort.
diff --git a/src/fns.c b/src/fns.c
index 2b1fb86419d..3cca40df50f 100644
--- a/src/fns.c
+++ b/src/fns.c
@@ -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
347DEFUN ("string-collate-lessp", Fstring_collate_lessp, Sstring_collate_lessp, 2, 2, 0, 347DEFUN ("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 349Symbols are also allowed; their print names are used instead.
350Case is significant. Symbols are also allowed; their print names are
351used instead.
352 350
353This function obeys the conventions for collation order in your 351This function obeys the conventions for collation order in your
354locale settings. For example, punctuation and whitespace characters 352locale settings. For example, punctuation and whitespace characters
355are considered less significant for sorting. 353are 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
360If your system does not support a locale environment, this function 358The optional argument LOCALE, a string, overrides the setting of your
361behaves like `string-lessp'. 359current locale identifier for collation. The value is system
360dependent; a LOCALE \"en_US.UTF-8\" is applicable on POSIX systems,
361while it would be \"English_USA.1252\" on MS Windows systems.
362 362
363If the environment variable \"LC_COLLATE\" is set in `process-environment', 363If IGNORE-CASE is non-nil, characters are converted to lower-case
364it overrides the setting of your current locale. */) 364before comparing them.
365 (Lisp_Object s1, Lisp_Object s2) 365
366If your system does not support a locale environment, this function
367behaves 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
383DEFUN ("string-collate-equalp", Fstring_collate_equalp, Sstring_collate_equalp, 2, 2, 0, 388DEFUN ("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 390Symbols are also allowed; their print names are used instead.
386Case is significant. Symbols are also allowed; their print names are
387used instead.
388 391
389This function obeys the conventions for collation order in your locale 392This function obeys the conventions for collation order in your locale
390settings. For example, characters with different coding points but 393settings. For example, characters with different coding points but
391the same meaning are considered as equal, like different grave accent 394the same meaning are considered as equal, like different grave accent
392unicode characters. 395unicode 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
397If your system does not support a locale environment, this function 400The optional argument LOCALE, a string, overrides the setting of your
398behaves like `string-equal'. 401current locale identifier for collation. The value is system
402dependent; a LOCALE \"en_US.UTF-8\" is applicable on POSIX systems,
403while it would be \"English_USA.1252\" on MS Windows systems.
399 404
400If the environment variable \"LC_COLLATE\" is set in `process-environment', 405If IGNORE-CASE is non-nil, characters are converted to lower-case
401it overrides the setting of your current locale. */) 406before comparing them.
402 (Lisp_Object s1, Lisp_Object s2) 407
408If your system does not support a locale environment, this function
409behaves 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);
4301extern void unlock_file (Lisp_Object); 4301extern void unlock_file (Lisp_Object);
4302extern void unlock_buffer (struct buffer *); 4302extern void unlock_buffer (struct buffer *);
4303extern void syms_of_filelock (void); 4303extern void syms_of_filelock (void);
4304extern int str_collate (Lisp_Object, Lisp_Object); 4304extern int str_collate (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object);
4305 4305
4306/* Defined in sound.c. */ 4306/* Defined in sound.c. */
4307extern void syms_of_sound (void); 4307extern 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
3628typedef char const *locale_t; 3638typedef 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
3697static wint_t
3698towlower_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
3688int 3720int
3689str_collate (Lisp_Object s1, Lisp_Object s2) 3721str_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
3739int 3792int
3740str_collate (Lisp_Object s1, Lisp_Object s2) 3793str_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}