emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] master 6220fae 4/4: casing: don’t assume letters are *eit


From: Michal Nazarewicz
Subject: [Emacs-diffs] master 6220fae 4/4: casing: don’t assume letters are *either* upper- or lower-case (bug#24603)
Date: Wed, 15 Feb 2017 11:46:34 -0500 (EST)

branch: master
commit 6220faeb4e9be16b9dec728e72ea8dff2cfe35ba
Author: Michal Nazarewicz <address@hidden>
Commit: Michal Nazarewicz <address@hidden>

    casing: don’t assume letters are *either* upper- or lower-case  (bug#24603)
    
    A compatibility digraph characters, such as Dž, are neither upper- nor
    lower-case.  At the moment however, those are reported as upper-case¹
    despite the fact that they change when upper-cased.
    
    Stop checking if a character is upper-case before trying to up-case it
    so that title-case characters are handled correctly.  This fixes one of
    the issues mentioned in bug#24603.
    
    ¹ Because they change when converted to lower-case.  Notice an asymmetry
      in that for a character to be considered lower-case it must not be
      upper-case (plus the usual condition of changing when upper-cased).
    
    * src/buffer.h (upcase1): Delete.
    (upcase): Change to upcase character unconditionally just like downcase
    does it.  This is what upcase1 was.
    
    * src/casefiddle.c (casify_object, casify_region): Use upcase instead
    of upcase1 and don’t check !uppercasep(x) before calling upcase.
    
    * src/keyboard.c (read_key_sequence): Don’t check if uppercase(x), just
    downcase(x) and see if it changed.
    
    * test/src/casefiddle-tests.el (casefiddle-tests--characters,
    casefiddle-tests-casing): Update test cases which are now passing.
---
 etc/NEWS                     |  8 +++++++-
 src/buffer.h                 | 18 +++++++++---------
 src/casefiddle.c             | 20 +++++++-------------
 src/keyboard.c               | 25 +++++++++++++++----------
 test/src/casefiddle-tests.el |  8 ++++----
 5 files changed, 42 insertions(+), 37 deletions(-)

diff --git a/etc/NEWS b/etc/NEWS
index 421e5da..a54c655 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -338,6 +338,12 @@ same as in modes where the character is not whitespace.
 Instead of only checking the modification time, Emacs now also checks
 the file's actual content before prompting the user.
 
+** Title case characters are properly converted to upper case.
+'upcase', 'upcase-region' et al. convert title case characters (such
+as Dz) into their upper case form (such as DZ).  As a downside,
+'capitalize' and 'upcase-initials' produce awkward words where first
+two letters are upper case, e.g. DŽungla (instead of Džungla).
+
 
 * Changes in Specialized Modes and Packages in Emacs 26.1
 
@@ -1028,7 +1034,7 @@ along with GNU Emacs.  If not, see 
<http://www.gnu.org/licenses/>.
 
 
 Local variables:
-coding: us-ascii
+coding: utf-8
 mode: outline
 paragraph-separate: "[         ]*$"
 end:
diff --git a/src/buffer.h b/src/buffer.h
index 4a23e4f..f53212e 100644
--- a/src/buffer.h
+++ b/src/buffer.h
@@ -1365,28 +1365,28 @@ downcase (int c)
   return NATNUMP (down) ? XFASTINT (down) : c;
 }
 
-/* True if C is upper case.  */
-INLINE bool uppercasep (int c) { return downcase (c) != c; }
-
-/* Upcase a character C known to be not upper case.  */
+/* Upcase a character C, or make no change if that cannot be done. */
 INLINE int
-upcase1 (int c)
+upcase (int c)
 {
   Lisp_Object upcase_table = BVAR (current_buffer, upcase_table);
   Lisp_Object up = CHAR_TABLE_REF (upcase_table, c);
   return NATNUMP (up) ? XFASTINT (up) : c;
 }
 
+/* True if C is upper case.  */
+INLINE bool uppercasep (int c)
+{
+  return downcase (c) != c;
+}
+
 /* True if C is lower case.  */
 INLINE bool
 lowercasep (int c)
 {
-  return !uppercasep (c) && upcase1 (c) != c;
+  return !uppercasep (c) && upcase (c) != c;
 }
 
-/* Upcase a character C, or make no change if that cannot be done.  */
-INLINE int upcase (int c) { return uppercasep (c) ? c : upcase1 (c); }
-
 INLINE_HEADER_END
 
 #endif /* EMACS_BUFFER_H */
diff --git a/src/casefiddle.c b/src/casefiddle.c
index 28ffcb2..b2b87e7 100644
--- a/src/casefiddle.c
+++ b/src/casefiddle.c
@@ -64,13 +64,9 @@ casify_object (enum case_action flag, Lisp_Object obj)
        multibyte = 1;
       if (! multibyte)
        MAKE_CHAR_MULTIBYTE (c1);
-      c = downcase (c1);
-      if (inword)
-       XSETFASTINT (obj, c | flags);
-      else if (c == (XFASTINT (obj) & ~flagbits))
+      c = flag == CASE_DOWN ? downcase (c1) : upcase (c1);
+      if (c != c1)
        {
-         if (! inword)
-           c = upcase1 (c1);
          if (! multibyte)
            MAKE_CHAR_UNIBYTE (c);
          XSETFASTINT (obj, c | flags);
@@ -95,7 +91,7 @@ casify_object (enum case_action flag, Lisp_Object obj)
            c = downcase (c);
          else if (!uppercasep (c)
                   && (!inword || flag != CASE_CAPITALIZE_UP))
-           c = upcase1 (c1);
+           c = upcase (c1);
          if ((int) flag >= (int) CASE_CAPITALIZE)
            inword = (SYNTAX (c) == Sword);
          if (c != c1)
@@ -127,9 +123,8 @@ casify_object (enum case_action flag, Lisp_Object obj)
          c = STRING_CHAR_AND_LENGTH (SDATA (obj) + i_byte, len);
          if (inword && flag != CASE_CAPITALIZE_UP)
            c = downcase (c);
-         else if (!uppercasep (c)
-                  && (!inword || flag != CASE_CAPITALIZE_UP))
-           c = upcase1 (c);
+         else if (!inword || flag != CASE_CAPITALIZE_UP)
+           c = upcase (c);
          if ((int) flag >= (int) CASE_CAPITALIZE)
            inword = (SYNTAX (c) == Sword);
          o += CHAR_STRING (c, o);
@@ -236,9 +231,8 @@ casify_region (enum case_action flag, Lisp_Object b, 
Lisp_Object e)
       c2 = c;
       if (inword && flag != CASE_CAPITALIZE_UP)
        c = downcase (c);
-      else if (!uppercasep (c)
-              && (!inword || flag != CASE_CAPITALIZE_UP))
-       c = upcase1 (c);
+      else if (!inword || flag != CASE_CAPITALIZE_UP)
+       c = upcase (c);
       if ((int) flag >= (int) CASE_CAPITALIZE)
        inword = ((SYNTAX (c) == Sword)
                  && (inword || !syntax_prefix_flag_p (c)));
diff --git a/src/keyboard.c b/src/keyboard.c
index ed8e71f..0fad633 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -9642,22 +9642,26 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, 
Lisp_Object prompt,
         use the corresponding lower-case letter instead.  */
       if (NILP (current_binding)
          && /* indec.start >= t && fkey.start >= t && */ keytran.start >= t
-         && INTEGERP (key)
-         && ((CHARACTERP (make_number (XINT (key) & ~CHAR_MODIFIER_MASK))
-              && uppercasep (XINT (key) & ~CHAR_MODIFIER_MASK))
-             || (XINT (key) & shift_modifier)))
+         && INTEGERP (key))
        {
          Lisp_Object new_key;
+         int k = XINT (key);
+
+         if (k & shift_modifier)
+           XSETINT (new_key, k & ~shift_modifier);
+         else if (CHARACTERP (make_number (k & ~CHAR_MODIFIER_MASK)))
+           {
+             int dc = downcase(k & ~CHAR_MODIFIER_MASK);
+             if (dc == (k & ~CHAR_MODIFIER_MASK))
+               goto not_upcase;
+             XSETINT (new_key, dc | (k & CHAR_MODIFIER_MASK));
+           }
+         else
+           goto not_upcase;
 
          original_uppercase = key;
          original_uppercase_position = t - 1;
 
-         if (XINT (key) & shift_modifier)
-           XSETINT (new_key, XINT (key) & ~shift_modifier);
-         else
-           XSETINT (new_key, (downcase (XINT (key) & ~CHAR_MODIFIER_MASK)
-                              | (XINT (key) & CHAR_MODIFIER_MASK)));
-
          /* We have to do this unconditionally, regardless of whether
             the lower-case char is defined in the keymaps, because they
             might get translated through function-key-map.  */
@@ -9668,6 +9672,7 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, 
Lisp_Object prompt,
          goto replay_sequence;
        }
 
+    not_upcase:
       if (NILP (current_binding)
          && help_char_p (EVENT_HEAD (key)) && t > 1)
            {
diff --git a/test/src/casefiddle-tests.el b/test/src/casefiddle-tests.el
index c752bb0..152d85d 100644
--- a/test/src/casefiddle-tests.el
+++ b/test/src/casefiddle-tests.el
@@ -63,13 +63,13 @@
     (?Ł ?Ł ?ł ?Ł)
     (?ł ?Ł ?ł ?Ł)
 
-    ;; FIXME(bug#24603): We should have:
+    ;; FIXME(bug#24603): Commented ones are what we want.
     ;;(?DŽ ?DŽ ?dž ?Dž)
-    ;; but instead we have:
     (?DŽ ?DŽ ?dž ?DŽ)
-    ;; FIXME(bug#24603): Those two are broken at the moment:
     ;;(?Dž ?DŽ ?dž ?Dž)
+    (?Dž ?DŽ ?dž ?DŽ)
     ;;(?dž ?DŽ ?dž ?Dž)
+    (?dž ?DŽ ?dž ?DŽ)
 
     (?Σ ?Σ ?σ ?Σ)
     (?σ ?Σ ?σ ?Σ)
@@ -197,7 +197,7 @@
         ;;("ΌΣΟΣ" "ΌΣΟΣ" "όσος" "Όσος" "Όσος")
         ;; And here’s what is actually happening:
         ("DŽUNGLA" "DŽUNGLA" "džungla" "DŽungla" "DŽUNGLA")
-        ("Džungla" "DžUNGLA" "džungla" "Džungla" "Džungla")
+        ("Džungla" "DŽUNGLA" "džungla" "DŽungla" "DŽungla")
         ("džungla" "DŽUNGLA" "džungla" "DŽungla" "DŽungla")
         ("define" "DEfiNE" "define" "Define" "Define")
         ("fish" "fiSH" "fish" "fish" "fish")



reply via email to

[Prev in Thread] Current Thread [Next in Thread]