changeset 89017:6a9e0cb7368b

(casify_object): Simplified. Handle the case that the case conversion change the byte length. (casify_region): Likewise
author Kenichi Handa <handa@m17n.org>
date Tue, 20 Aug 2002 03:58:53 +0000
parents 82f852ddca70
children a9f683a73092
files src/casefiddle.c
diffstat 1 files changed, 83 insertions(+), 114 deletions(-) [+]
line wrap: on
line diff
--- a/src/casefiddle.c	Tue Aug 20 03:58:23 2002 +0000
+++ b/src/casefiddle.c	Tue Aug 20 03:58:53 2002 +0000
@@ -37,7 +37,7 @@
      enum case_action flag;
      Lisp_Object obj;
 {
-  register int i, c, len;
+  register int c, c1;
   register int inword = flag == CASE_DOWN;
 
   /* If the case table is flagged as modified, rescan it.  */
@@ -51,13 +51,22 @@
 	  int flagbits = (CHAR_ALT | CHAR_SUPER | CHAR_HYPER
 			  | CHAR_SHIFT | CHAR_CTL | CHAR_META);
 	  int flags = XINT (obj) & flagbits;
+	  int multibyte = ! NILP (current_buffer->enable_multibyte_characters);
 
-	  c = DOWNCASE (XFASTINT (obj) & ~flagbits);
-	  if (inword)
-	    XSETFASTINT (obj, c | flags);
-	  else if (c == (XFASTINT (obj) & ~flagbits))
+	  c1 = XFASTINT (obj) & ~flagbits;
+	  if (! multibyte)
 	    {
-	      c = UPCASE1 ((XFASTINT (obj) & ~flagbits));
+	      MAKE_CHAR_UNIBYTE (c1);
+	    }
+	  c = DOWNCASE (c1);
+	  if (inword || c == c1)
+	    {
+	      if (! inword)
+		c = UPCASE1 (c1);
+	      if (! multibyte)
+		{
+		  MAKE_CHAR_MULTIBYTE (c);
+		}
 	      XSETFASTINT (obj, c | flags);
 	    }
 	  return obj;
@@ -66,66 +75,44 @@
       if (STRINGP (obj))
 	{
 	  int multibyte = STRING_MULTIBYTE (obj);
+	  int i, i_byte, len;
+	  int size = XSTRING (obj)->size;
 
 	  obj = Fcopy_sequence (obj);
-	  len = STRING_BYTES (XSTRING (obj));
-
-	  /* Scan all single-byte characters from start of string.  */
-	  for (i = 0; i < len;)
+	  for (i = i_byte = 0; i < size; i++, i_byte += len)
 	    {
-	      c = XSTRING (obj)->data[i];
-
-	      if (multibyte && c >= 0x80)
-		/* A multibyte character can't be handled in this
-                   simple loop.  */
-		break;
+	      if (multibyte)
+		c = STRING_CHAR_AND_LENGTH (XSTRING (obj)->data + i_byte,
+					    0, len);
+	      else
+		{
+		  c = XSTRING (obj)->data[i_byte];
+		  len = 1;
+		  MAKE_CHAR_MULTIBYTE (c);
+		}
+	      c1 = c; 
 	      if (inword && flag != CASE_CAPITALIZE_UP)
 		c = DOWNCASE (c);
 	      else if (!UPPERCASEP (c)
 		       && (!inword || flag != CASE_CAPITALIZE_UP))
-		c = UPCASE1 (c);
-	      /* If this char won't fit in a single-byte string.
-		 fall out to the multibyte case.  */
-	      if (multibyte ? ! ASCII_BYTE_P (c)
-		  : ! SINGLE_BYTE_CHAR_P (c))
-		break;
-
-	      XSTRING (obj)->data[i] = c;
+		c = UPCASE1 (c1);
 	      if ((int) flag >= (int) CASE_CAPITALIZE)
 		inword = SYNTAX (c) == Sword;
-	      i++;
-	    }
-
-	  /* If we didn't do the whole string as single-byte,
-	     scan the rest in a more complex way.  */
-	  if (i < len)
-	    {
-	      /* The work is not yet finished because of a multibyte
-		 character just encountered.  */
-	      int fromlen, j_byte = i;
-	      char *buf
-		= (char *) alloca ((len - i) * MAX_MULTIBYTE_LENGTH + i);
-
-	      /* Copy data already handled.  */
-	      bcopy (XSTRING (obj)->data, buf, i);
-
-	      /* From now on, I counts bytes.  */
-	      while (i < len)
+	      if (c != c1)
 		{
-		  c = STRING_CHAR_AND_LENGTH (XSTRING (obj)->data + i,
-					      len - i, fromlen);
-		  if (inword && flag != CASE_CAPITALIZE_UP)
-		    c = DOWNCASE (c);
-		  else if (!UPPERCASEP (c)
-			   && (!inword || flag != CASE_CAPITALIZE_UP))
-		    c = UPCASE1 (c);
-		  i += fromlen;
-		  j_byte += CHAR_STRING (c, buf + j_byte);
-		  if ((int) flag >= (int) CASE_CAPITALIZE)
-		    inword = SYNTAX (c) == Sword;
+		  if (! multibyte)
+		    {
+		      MAKE_CHAR_UNIBYTE (c);
+		      XSTRING (obj)->data[i_byte] = c;
+		    }
+		  else if (ASCII_CHAR_P (c1) && ASCII_CHAR_P (c))
+		    XSTRING (obj)->data[i_byte] = c;
+		  else
+		    {
+		      Faset (obj, make_number (i), make_number (c));
+		      i_byte += CHAR_BYTES (c) - len;
+		    }
 		}
-	      obj = make_multibyte_string (buf, XSTRING (obj)->size,
-					   j_byte);
 	    }
 	  return obj;
 	}
@@ -194,6 +181,8 @@
   int start, end;
   int start_byte, end_byte;
   int changed = 0;
+  int opoint = PT;
+  int opoint_byte = PT_BYTE;
 
   if (EQ (b, e))
     /* Not modifying because nothing marked */
@@ -211,83 +200,63 @@
   start_byte = CHAR_TO_BYTE (start);
   end_byte = CHAR_TO_BYTE (end);
 
-  for (i = start_byte; i < end_byte; i++, start++)
+  while (start < end)
     {
-      int c2;
-      c = c2 = FETCH_BYTE (i);
-      if (multibyte && c >= 0x80)
-	/* A multibyte character can't be handled in this simple loop.  */
-	break;
+      int c2, len;
+
+      if (multibyte)
+	{
+	  c = FETCH_MULTIBYTE_CHAR (start_byte);
+	  len = CHAR_BYTES (c);
+	}
+      else
+	{
+	  c = FETCH_BYTE (start_byte);
+	  MAKE_CHAR_MULTIBYTE (c);
+	  len = 1;
+	}
+      c2 = c;
       if (inword && flag != CASE_CAPITALIZE_UP)
 	c = DOWNCASE (c);
       else if (!UPPERCASEP (c)
 	       && (!inword || flag != CASE_CAPITALIZE_UP))
 	c = UPCASE1 (c);
-      FETCH_BYTE (i) = c;
-      if (c != c2)
-	changed = 1;
       if ((int) flag >= (int) CASE_CAPITALIZE)
 	inword = SYNTAX (c) == Sword;
-    }
-  if (i < end_byte)
-    {
-      /* The work is not yet finished because of a multibyte character
-	 just encountered.  */
-      int opoint = PT;
-      int opoint_byte = PT_BYTE;
-      int c2;
-
-      while (i < end_byte)
+      if (c != c2)
 	{
-	  if ((c = FETCH_BYTE (i)) >= 0x80)
-	    c = FETCH_MULTIBYTE_CHAR (i);
-	  c2 = c;
-	  if (inword && flag != CASE_CAPITALIZE_UP)
-	    c2 = DOWNCASE (c);
-	  else if (!UPPERCASEP (c)
-		   && (!inword || flag != CASE_CAPITALIZE_UP))
-	    c2 = UPCASE1 (c);
-	  if (c != c2)
+	  changed = 1;
+	  if (! multibyte)
 	    {
-	      int fromlen, tolen, j;
+	      MAKE_CHAR_UNIBYTE (c);
+	      FETCH_BYTE (start_byte) = c;
+	    }
+	  else if (ASCII_CHAR_P (c2) && ASCII_CHAR_P (c))
+	    FETCH_BYTE (start_byte) = c;
+	  else if (len == CHAR_BYTES (c))
+	    {
+	      int j;
 	      unsigned char str[MAX_MULTIBYTE_LENGTH];
 
-	      changed = 1;
-	      /* Handle the most likely case */
-	      if (multibyte ? (c < 0200 && c2 < 0200)
-		  : (c < 0400 && c2 < 0400))
-		FETCH_BYTE (i) = c2;
-	      else if (fromlen = CHAR_STRING (c, str),
-		       tolen = CHAR_STRING (c2, str),
-		       fromlen == tolen)
-		{
-		  for (j = 0; j < tolen; ++j)
-		    FETCH_BYTE (i + j) = str[j];
-		}
-	      else
-		{
-		  error ("Can't casify letters that change length");
-#if 0 /* This is approximately what we'd like to be able to do here */
-		  if (tolen < fromlen)
-		    del_range_1 (i + tolen, i + fromlen, 0, 0);
-		  else if (tolen > fromlen)
-		    {
-		      TEMP_SET_PT (i + fromlen);
-		      insert_1 (str + fromlen, tolen - fromlen, 1, 0, 0);
-		    }
-#endif
-		}
+	      CHAR_STRING (c, str);
+	      for (j = 0; j < len; ++j)
+		FETCH_BYTE (start_byte + j) = str[j];
 	    }
-	  if ((int) flag >= (int) CASE_CAPITALIZE)
-	    inword = SYNTAX (c2) == Sword;
-	  INC_BOTH (start, i);
+	  else
+	    {
+	      TEMP_SET_PT_BOTH (start, start_byte);
+	      del_range_2 (start, start_byte, start + 1, start_byte + len, 0);
+	      insert_char (c);
+	      len = CHAR_BYTES (c);
+	    }
 	}
-      TEMP_SET_PT_BOTH (opoint, opoint_byte);
+      start++;
+      start_byte += len;
     }
 
-  start = XFASTINT (b);
   if (changed)
     {
+      start = XFASTINT (b);
       signal_after_change (start, end - start, end - start);
       update_compositions (start, end, CHECK_ALL);
     }