# HG changeset patch # User Kenichi Handa # Date 958780226 0 # Node ID d8c9e2f7022fe11d72f08a9868b97d2e71c3e0ee # Parent fc8d42f77d4f7641a7dc1c7fccadf9eae4e79dad (advance_to_char_boundary): Don't use DEC_POS to find a apparent char boundary. (Fset_buffer_multibyte): Convert 8-bit characters in the range 0x80..0x9F to/from multibyte form. diff -r fc8d42f77d4f -r d8c9e2f7022f src/buffer.c --- a/src/buffer.c Fri May 19 23:49:35 2000 +0000 +++ b/src/buffer.c Fri May 19 23:50:26 2000 +0000 @@ -1843,8 +1843,17 @@ { /* We should advance BYTE_POS only when C is a constituent of a multibyte sequence. */ - DEC_POS (byte_pos); + int orig_byte_pos = byte_pos; + + do + { + byte_pos--; + c = FETCH_BYTE (byte_pos); + } + while (! CHAR_HEAD_P (c) && byte_pos > BEG); INC_POS (byte_pos); + if (byte_pos < orig_byte_pos) + byte_pos = orig_byte_pos; /* If C is a constituent of a multibyte sequence, BYTE_POS was surely advance to the correct character boundary. If C is not, BYTE_POS was unchanged. */ @@ -1865,6 +1874,9 @@ { Lisp_Object tail, markers; struct buffer *other; + int undo_enabled_p = !EQ (current_buffer->undo_list, Qt); + int begv = BEGV, zv = ZV; + int narrowed = (BEG != begv || Z != zv); if (current_buffer->base_buffer) error ("Cannot do `set-buffer-multibyte' on an indirect buffer"); @@ -1875,14 +1887,20 @@ /* It would be better to update the list, but this is good enough for now. */ - if (! EQ (current_buffer->undo_list, Qt)) - current_buffer->undo_list = Qnil; + if (undo_enabled_p) + current_buffer->undo_list = Qt; /* If the cached position is for this buffer, clear it out. */ clear_charpos_cache (current_buffer); + if (narrowed) + Fwiden (); + if (NILP (flag)) { + int pos, stop; + unsigned char *p; + /* Do this first, so it can use CHAR_TO_BYTE to calculate the old correspondences. */ set_intervals_multibyte (0); @@ -1901,12 +1919,54 @@ XMARKER (tail)->charpos = XMARKER (tail)->bytepos; tail = XMARKER (tail)->chain; } + + /* Convert multibyte form of 8-bit characters to unibyte. */ + pos = BEG; + stop = GPT; + p = BEG_ADDR; + while (1) + { + int c, bytes; + + if (pos == stop) + { + if (pos == Z) + break; + p = GAP_END_ADDR; + stop = Z; + } + if (MULTIBYTE_STR_AS_UNIBYTE_P (p, bytes)) + p += bytes, pos += bytes; + else + { + c = STRING_CHAR (p, stop - pos); + /* Delete all bytes for this 8-bit character but the + last one, and change the last one to the charcter + code. */ + bytes--; + del_range_2 (pos, pos, pos + bytes, pos + bytes, 0); + p = GAP_END_ADDR; + *p++ = c; + pos++; + if (begv > pos) + begv -= bytes; + if (zv > pos) + zv -= bytes; + stop = Z; + } + } + if (narrowed) + Fnarrow_to_region (make_number (begv), make_number (zv)); } else { + int pt = PT; + int pos, stop; + unsigned char *p; + /* Be sure not to have a multibyte sequence striding over the GAP. - Ex: We change this: "...abc\201\241\241 _GAP_ \241\241\241..." - to: "...abc _GAP_ \201\241\241\241\241\241..." */ + Ex: We change this: "...abc\201 _GAP_ \241def..." + to: "...abc _GAP_ \201\241def..." */ if (GPT_BYTE > 1 && GPT_BYTE < Z_BYTE && ! CHAR_HEAD_P (*(GAP_END_ADDR))) @@ -1922,6 +1982,53 @@ } } + /* Make the buffer contents valid as multibyte by converting + 8-bit characters to multibyte form. */ + pos = BEG; + stop = GPT; + p = BEG_ADDR; + while (1) + { + int bytes; + + if (pos == stop) + { + if (pos == Z) + break; + p = GAP_END_ADDR; + stop = Z; + } + + if (UNIBYTE_STR_AS_MULTIBYTE_P (p, stop - pos, bytes)) + p += bytes, pos += bytes; + else + { + unsigned char tmp[MAX_MULTIBYTE_LENGTH]; + + bytes = CHAR_STRING (*p, tmp); + *p = tmp[0]; + TEMP_SET_PT_BOTH (pos + 1, pos + 1); + bytes--; + insert_1_both (tmp + 1, bytes, bytes, 1, 0, 0); + /* Now the gap is after the just inserted data. */ + pos = GPT; + p = GAP_END_ADDR; + if (pos <= begv) + begv += bytes; + if (pos <= zv) + zv += bytes; + if (pos <= pt) + pt += bytes; + stop = Z; + } + } + + if (pt != PT) + TEMP_SET_PT (pt); + + if (narrowed) + Fnarrow_to_region (make_number (begv), make_number (zv)); + /* Do this first, so that chars_in_text asks the right question. set_intervals_multibyte needs it too. */ current_buffer->enable_multibyte_characters = Qt; @@ -1982,6 +2089,9 @@ set_intervals_multibyte (1); } + if (undo_enabled_p) + current_buffer->undo_list = Qnil; + /* Changing the multibyteness of a buffer means that all windows showing that buffer must be updated thoroughly. */ current_buffer->prevent_redisplay_optimizations_p = 1;