# HG changeset patch # User Richard M. Stallman # Date 889654104 0 # Node ID f4df45f5a0e25696284e10c60f312210fd2b648f # Parent be04baf3d9704b617923e67febaea97e10279e4e (combine_bytes): New function. (insert_1_both, insert_from_string_1, insert_from_buffer_1): Simplify greatly by using combine_bytes near the end to handle all aspects of combining except for undo-recording. This means most of the code deals with the text as if there were no combining. (replace_range): Likewise. Also handle unibyte-multibyte conversion as in insert_from_string_1. (del_range_2): Handle combining of character before the deletion with strays after the deletion. (adjust_markers_for_delete): Delete debugging code for Z == Z_BYTE. (adjust_markers_for_insert): Move Z == Z_BYTE debugging code to before we relocate the marker. diff -r be04baf3d970 -r f4df45f5a0e2 src/insdel.c --- a/src/insdel.c Wed Mar 11 00:47:48 1998 +0000 +++ b/src/insdel.c Wed Mar 11 22:08:24 1998 +0000 @@ -368,24 +368,6 @@ m->bytepos = from_byte; } - /* In a single-byte buffer, a marker's two positions must be equal. */ - if (Z == Z_BYTE) - { - register int i = m->bytepos; - -#if 0 - /* We use FROM_BYTE here instead of GPT_BYTE - because FROM_BYTE is where the gap will be after the deletion. */ - if (i > from_byte + coming_gap_size) - i -= coming_gap_size; - else if (i > from_byte) - i = from_byte; -#endif - - if (m->charpos != i) - abort (); - } - marker = m->chain; } } @@ -420,6 +402,17 @@ while (!NILP (marker)) { register struct Lisp_Marker *m = XMARKER (marker); + + /* In a single-byte buffer, a marker's two positions must be equal. + (If this insertion is going to combine characters, Z will + become different from Z_BYTE, but they might be the same now. + If so, the two OLD positions of the marker should be equal.) */ + if (Z == Z_BYTE) + { + if (m->charpos != m->bytepos) + abort (); + } + if (m->bytepos == from_byte) { if (m->insertion_type || before_markers) @@ -465,13 +458,6 @@ m->charpos += nchars; } - /* In a single-byte buffer, a marker's two positions must be equal. */ - if (Z == Z_BYTE) - { - if (m->charpos != m->bytepos) - abort (); - } - marker = m->chain; } @@ -762,7 +748,7 @@ signal_after_change (opoint, 0, PT - opoint); } } - + /* Subroutine used by the insert functions above. */ void @@ -774,7 +760,7 @@ insert_1_both (string, chars_in_text (string, nbytes), nbytes, inherit, prepare, before_markers); } - + /* See if the bytes before POS/POS_BYTE combine with bytes at the start of STRING to form a single character. If so, return the number of bytes at the start of STRING @@ -855,6 +841,34 @@ return pos_byte - opos_byte; } +/* Combine NBYTES stray trailing-codes, which were formerly separate + characters, with the preceding character. These bytes + are located after position POS / POS_BYTE, and the preceding character + is located just before that position. */ + +static void +combine_bytes (pos, pos_byte, nbytes) + int pos, pos_byte, nbytes; +{ + /* Adjust all markers. */ + adjust_markers_for_delete (pos, pos_byte, pos + nbytes, pos_byte); + + adjust_overlays_for_delete (pos, nbytes); + + if (PT > pos) + BUF_PT (current_buffer) -= nbytes; + if (GPT > pos) + GPT -= nbytes; + if (Z > pos) + Z -= nbytes; + if (ZV > pos) + ZV -= nbytes; + + if (BUF_INTERVALS (current_buffer) != 0) + /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES. */ + offset_intervals (current_buffer, pos, - nbytes); +} + /* Insert a sequence of NCHARS chars which occupy NBYTES bytes starting at STRING. INHERIT, PREPARE and BEFORE_MARKERS are the same as in insert_1. */ @@ -867,7 +881,6 @@ { register Lisp_Object temp; int combined_before_bytes, combined_after_bytes; - int adjusted_nchars; if (NILP (current_buffer->enable_multibyte_characters)) nchars = nbytes; @@ -877,17 +890,13 @@ if (GAP_SIZE < nbytes) make_gap (nbytes - GAP_SIZE); - combined_before_bytes = count_combining_before (string, nbytes, PT, PT_BYTE); - combined_after_bytes = count_combining_after (string, nbytes, PT, PT_BYTE); - - /* This is the net amount that Z will increase from this insertion. */ + if (prepare) + prepare_to_modify_buffer (PT, PT, NULL); - adjusted_nchars = nchars - combined_before_bytes - combined_after_bytes; - - if (prepare) - prepare_to_modify_buffer (PT - !!combined_before_bytes, - PT + combined_after_bytes, - NULL); + combined_before_bytes + = count_combining_before (string, nbytes, PT, PT_BYTE); + combined_after_bytes + = count_combining_after (string, nbytes, PT, PT_BYTE); /* Record deletion of the surrounding text that combines with the insertion. This, together with recording the insertion, @@ -907,49 +916,52 @@ bcopy (string, GPT_ADDR, nbytes); -#ifdef USE_TEXT_PROPERTIES - if (BUF_INTERVALS (current_buffer) != 0) - /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES. */ - offset_intervals (current_buffer, PT, adjusted_nchars); -#endif - GAP_SIZE -= nbytes; /* When we have combining at the end of the insertion, this is the character position before the combined character. */ - GPT += nchars - combined_before_bytes - !!combined_after_bytes; - ZV += adjusted_nchars; - Z += adjusted_nchars; + GPT += nchars; + ZV += nchars; + Z += nchars; GPT_BYTE += nbytes; ZV_BYTE += nbytes; Z_BYTE += nbytes; if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */ - adjust_overlays_for_insert (PT, adjusted_nchars); + + if (combined_after_bytes) + move_gap_both (GPT + combined_after_bytes, + GPT_BYTE + combined_after_bytes); + + if (GPT_BYTE < GPT) + abort (); + + adjust_overlays_for_insert (PT, nchars); adjust_markers_for_insert (PT, PT_BYTE, - PT + adjusted_nchars, PT_BYTE + nbytes, + PT + nchars, PT_BYTE + nbytes, combined_before_bytes, combined_after_bytes, before_markers); - /* "Delete" the combined-after bytes, as far as intervals are concerned. - Note that as far as the intervals are concerned, - no insertion has yet taken place, so these bytes are right after PT. */ - if (combined_after_bytes) - offset_intervals (current_buffer, PT, - combined_after_bytes); +#ifdef USE_TEXT_PROPERTIES + if (BUF_INTERVALS (current_buffer) != 0) + /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES. */ + offset_intervals (current_buffer, PT, nchars); -#ifdef USE_TEXT_PROPERTIES if (!inherit && BUF_INTERVALS (current_buffer) != 0) - Fset_text_properties (make_number (PT), - make_number (PT + adjusted_nchars + combined_after_bytes), + Fset_text_properties (make_number (PT), make_number (PT + nchars), Qnil, Qnil); #endif - adjust_point (adjusted_nchars + combined_after_bytes, - nbytes + combined_after_bytes); + { + int pos = PT, pos_byte = PT_BYTE; + + adjust_point (nchars + combined_after_bytes, + nbytes + combined_after_bytes); - if (combined_after_bytes) - move_gap_both (GPT + 1, GPT_BYTE + combined_after_bytes); + if (combined_after_bytes) + combine_bytes (pos + nchars, pos_byte + nbytes, combined_after_bytes); - if (GPT_BYTE < GPT) - abort (); + if (combined_before_bytes) + combine_bytes (pos, pos_byte, combined_before_bytes); + } } /* Insert the part of the text of STRING, a Lisp object assumed to be @@ -1052,14 +1064,9 @@ the text that has been stored by copy_text. */ combined_before_bytes - = count_combining_before (XSTRING (string)->data + pos_byte, nbytes, - PT, PT_BYTE); + = count_combining_before (GPT_ADDR, outgoing_nbytes, PT, PT_BYTE); combined_after_bytes - = count_combining_after (XSTRING (string)->data + pos_byte, nbytes, - PT, PT_BYTE); - - /* This is the net amount that Z will increase from this insertion. */ - adjusted_nchars = nchars - combined_before_bytes - combined_after_bytes; + = count_combining_after (GPT_ADDR, outgoing_nbytes, PT, PT_BYTE); /* Record deletion of the surrounding text that combines with the insertion. This, together with recording the insertion, @@ -1077,49 +1084,54 @@ record_insert (PT - !!combined_before_bytes, nchars); MODIFF++; - /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */ - offset_intervals (current_buffer, PT, adjusted_nchars); - GAP_SIZE -= outgoing_nbytes; - GPT += nchars - combined_before_bytes - !!combined_after_bytes; - ZV += adjusted_nchars; - Z += adjusted_nchars; + GPT += nchars; + ZV += nchars; + Z += nchars; GPT_BYTE += outgoing_nbytes; ZV_BYTE += outgoing_nbytes; Z_BYTE += outgoing_nbytes; if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */ - adjust_overlays_for_insert (PT, adjusted_nchars); - adjust_markers_for_insert (PT, PT_BYTE, PT + adjusted_nchars, + + if (combined_after_bytes) + move_gap_both (GPT + combined_after_bytes, + GPT_BYTE + combined_after_bytes); + + if (GPT_BYTE < GPT) + abort (); + + adjust_overlays_for_insert (PT, nchars); + adjust_markers_for_insert (PT, PT_BYTE, PT + nchars, PT_BYTE + outgoing_nbytes, combined_before_bytes, combined_after_bytes, before_markers); - if (combined_after_bytes) - move_gap_both (GPT + 1, GPT_BYTE + combined_after_bytes); - - if (GPT_BYTE < GPT) - abort (); + /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */ + offset_intervals (current_buffer, PT, nchars); - /* "Delete" the combined-after bytes, as far as intervals are concerned. - Note that as far as the intervals are concerned, - no insertion has yet taken place, so these bytes are right after PT. */ - if (combined_after_bytes) - offset_intervals (current_buffer, PT, - combined_after_bytes); - + intervals = XSTRING (string)->intervals; /* Get the intervals for the part of the string we are inserting-- not including the combined-before bytes. */ - intervals = XSTRING (string)->intervals; - if (combined_before_bytes != 0 - || nbytes < XSTRING (string)->size_byte) - intervals = copy_intervals (intervals, pos + combined_before_bytes, - nchars - combined_before_bytes); + if (nbytes < XSTRING (string)->size_byte) + intervals = copy_intervals (intervals, pos, nchars); /* Insert those intervals. */ - graft_intervals_into_buffer (intervals, PT, nchars - combined_before_bytes, + graft_intervals_into_buffer (intervals, PT, nchars, current_buffer, inherit); - adjust_point (adjusted_nchars + combined_after_bytes, - outgoing_nbytes + combined_after_bytes); + { + int pos = PT, pos_byte = PT_BYTE; + + adjust_point (nchars + combined_after_bytes, + outgoing_nbytes + combined_after_bytes); + + if (combined_after_bytes) + combine_bytes (pos + nchars, pos_byte + outgoing_nbytes, + combined_after_bytes); + + if (combined_before_bytes) + combine_bytes (pos, pos_byte, combined_before_bytes); + } } /* Insert text from BUF, NCHARS characters starting at CHARPOS, into the @@ -1203,17 +1215,14 @@ /* We have copied text into the gap, but we have not altered PT or PT_BYTE yet. So we can pass PT and PT_BYTE to these functions and get the same results as we would - have got earlier on. Meanwhile, PT_ADDR does point to + have got earlier on. Meanwhile, GPT_ADDR does point to the text that has been stored by copy_text. */ combined_before_bytes - = count_combining_before (PT_ADDR, outgoing_nbytes, PT, PT_BYTE); + = count_combining_before (GPT_ADDR, outgoing_nbytes, PT, PT_BYTE); combined_after_bytes - = count_combining_after (PT_ADDR, outgoing_nbytes, + = count_combining_after (GPT_ADDR, outgoing_nbytes, PT, PT_BYTE); - /* This is the net amount that Z will increase from this insertion. */ - adjusted_nchars = nchars - combined_before_bytes - combined_after_bytes; - /* Record deletion of the surrounding text that combines with the insertion. This, together with recording the insertion, will add up to the right stuff in the undo list. @@ -1230,51 +1239,54 @@ record_insert (PT - !!combined_before_bytes, nchars); MODIFF++; -#ifdef USE_TEXT_PROPERTIES - if (BUF_INTERVALS (current_buffer) != 0) - offset_intervals (current_buffer, PT, adjusted_nchars); -#endif - GAP_SIZE -= outgoing_nbytes; - GPT += nchars - combined_before_bytes - !!combined_after_bytes; - ZV += adjusted_nchars; - Z += adjusted_nchars; + GPT += nchars; + ZV += nchars; + Z += nchars; GPT_BYTE += outgoing_nbytes; ZV_BYTE += outgoing_nbytes; Z_BYTE += outgoing_nbytes; if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */ - adjust_overlays_for_insert (PT, adjusted_nchars); - adjust_markers_for_insert (PT, PT_BYTE, PT + adjusted_nchars, + + if (combined_after_bytes) + move_gap_both (GPT + combined_after_bytes, + GPT_BYTE + combined_after_bytes); + + if (GPT_BYTE < GPT) + abort (); + + adjust_overlays_for_insert (PT, nchars); + adjust_markers_for_insert (PT, PT_BYTE, PT + nchars, PT_BYTE + outgoing_nbytes, combined_before_bytes, combined_after_bytes, 0); - /* "Delete" the combined-after bytes, as far as intervals are concerned. - Note that as far as the intervals are concerned, - no insertion has yet taken place, so these bytes are right after PT. */ - if (combined_after_bytes) - offset_intervals (current_buffer, PT, - combined_after_bytes); +#ifdef USE_TEXT_PROPERTIES + if (BUF_INTERVALS (current_buffer) != 0) + offset_intervals (current_buffer, PT, nchars); +#endif /* Get the intervals for the part of the string we are inserting-- not including the combined-before bytes. */ intervals = BUF_INTERVALS (buf); - if (combined_before_bytes != 0 - || nbytes < BUF_Z_BYTE (buf) - BUF_BEG_BYTE (buf)) - intervals = copy_intervals (intervals, from + combined_before_bytes, - nchars - combined_before_bytes); + if (outgoing_nbytes < BUF_Z_BYTE (buf) - BUF_BEG_BYTE (buf)) + intervals = copy_intervals (intervals, from, nchars); /* Insert those intervals. */ - graft_intervals_into_buffer (intervals, PT, nchars - combined_before_bytes, - current_buffer, inherit); + graft_intervals_into_buffer (intervals, PT, nchars, current_buffer, inherit); + { + int pos = PT, pos_byte = PT_BYTE; + + adjust_point (nchars + combined_after_bytes, + outgoing_nbytes + combined_after_bytes); - adjust_point (adjusted_nchars + combined_after_bytes, - outgoing_nbytes + combined_after_bytes); + if (combined_after_bytes) + combine_bytes (pos + nchars, pos_byte + outgoing_nbytes, + combined_after_bytes); - if (combined_after_bytes) - move_gap_both (GPT + 1, GPT_BYTE + combined_after_bytes); - - if (GPT_BYTE < GPT) - abort (); + if (combined_before_bytes) + combine_bytes (pos, pos_byte, combined_before_bytes); + } } /* This function should be called after moving gap to FROM and before @@ -1344,6 +1356,7 @@ int combined_before_bytes, combined_after_bytes; int adjusted_inschars; INTERVAL intervals; + int outgoing_insbytes = insbytes; GCPRO1 (new); @@ -1371,6 +1384,15 @@ if (nbytes_del <= 0 && insbytes == 0) return; + /* Make OUTGOING_INSBYTES describe the text + as it will be inserted in this buffer. */ + + if (NILP (current_buffer->enable_multibyte_characters)) + outgoing_insbytes = inschars; + else if (inschars == insbytes) + outgoing_insbytes + = count_size_as_multibyte (XSTRING (new)->data, insbytes); + /* Make sure point-max won't overflow after this insertion. */ XSETINT (temp, Z_BYTE - nbytes_del + insbytes); if (Z_BYTE - nbytes_del + insbytes != XINT (temp)) @@ -1412,20 +1434,26 @@ if (GAP_SIZE < insbytes) make_gap (insbytes - GAP_SIZE); + /* Copy the string text into the buffer, perhaps converting + between single-byte and multibyte. */ + copy_text (XSTRING (new)->data, GPT_ADDR, insbytes, + /* If these are equal, it is a single-byte string. + Its chars are either ASCII, in which case copy_text + won't change it, or single-byte non-ASCII chars, + that need to be changed. */ + inschars != insbytes, + ! NILP (current_buffer->enable_multibyte_characters)); + /* We have copied text into the gap, but we have not altered PT or PT_BYTE yet. So we can pass PT and PT_BYTE to these functions and get the same results as we would - have got earlier on. Meanwhile, PT_ADDR does point to + have got earlier on. Meanwhile, GPT_ADDR does point to the text that has been stored by copy_text. */ combined_before_bytes - = count_combining_before (XSTRING (new)->data, insbytes, PT, PT_BYTE); + = count_combining_before (GPT_ADDR, outgoing_insbytes, PT, PT_BYTE); combined_after_bytes - = count_combining_after (XSTRING (new)->data, insbytes, PT, PT_BYTE); - - /* This is the net amount that Z will increase from this insertion. */ - adjusted_inschars - = inschars - combined_before_bytes - combined_after_bytes; + = count_combining_after (GPT_ADDR, outgoing_insbytes, PT, PT_BYTE); /* Record deletion of the surrounding text that combines with the insertion. This, together with recording the insertion, @@ -1442,28 +1470,18 @@ record_insert (from, inschars); - bcopy (XSTRING (new)->data, GPT_ADDR, insbytes); - - /* Relocate point as if it were a marker. */ - if (from < PT) - adjust_point ((from + adjusted_inschars - (PT < to ? PT : to) - + combined_after_bytes), - (from_byte + insbytes - - (PT_BYTE < to_byte ? PT_BYTE : to_byte) - + combined_after_bytes)); + GAP_SIZE -= outgoing_insbytes; + GPT += inschars; + ZV += inschars; + Z += inschars; + GPT_BYTE += outgoing_insbytes; + ZV_BYTE += outgoing_insbytes; + Z_BYTE += outgoing_insbytes; + if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */ -#ifdef USE_TEXT_PROPERTIES - offset_intervals (current_buffer, PT, adjusted_inschars - nchars_del); -#endif - - GAP_SIZE -= insbytes; - GPT += inschars - combined_before_bytes - !!combined_after_bytes; - ZV += adjusted_inschars; - Z += adjusted_inschars; - GPT_BYTE += insbytes; - ZV_BYTE += insbytes; - ZV_BYTE += insbytes; - if (GAP_SIZE > 0) *(GPT_ADDR) = 0; /* Put an anchor. */ + if (combined_after_bytes) + move_gap_both (GPT + combined_after_bytes, + GPT_BYTE + combined_after_bytes); if (GPT_BYTE < GPT) abort (); @@ -1471,39 +1489,44 @@ /* Adjust the overlay center as needed. This must be done after adjusting the markers that bound the overlays. */ adjust_overlays_for_delete (from, nchars_del); - adjust_overlays_for_insert (from, adjusted_inschars); - adjust_markers_for_insert (from, from_byte, from + adjusted_inschars, - from_byte + insbytes, + adjust_overlays_for_insert (from, inschars); + adjust_markers_for_insert (from, from_byte, + from + inschars, from_byte + outgoing_insbytes, combined_before_bytes, combined_after_bytes, 0); - /* "Delete" the combined-after bytes, as far as intervals are concerned. - Note that as far as the intervals are concerned, - no insertion has yet taken place, so these bytes are right after PT. */ - if (combined_after_bytes) - offset_intervals (current_buffer, PT, - combined_after_bytes); +#ifdef USE_TEXT_PROPERTIES + offset_intervals (current_buffer, PT, inschars - nchars_del); /* Get the intervals for the part of the string we are inserting-- not including the combined-before bytes. */ intervals = XSTRING (new)->intervals; - if (combined_before_bytes != 0) - intervals = copy_intervals (intervals, combined_before_bytes, - inschars - combined_before_bytes); - /* Insert those intervals. */ - graft_intervals_into_buffer (intervals, from, - inschars - combined_before_bytes, + graft_intervals_into_buffer (intervals, from, inschars, current_buffer, inherit); +#endif - if (insbytes == 0) - evaporate_overlays (from); + /* Relocate point as if it were a marker. */ + if (from < PT) + adjust_point ((from + inschars - (PT < to ? PT : to) + + combined_after_bytes), + (from_byte + outgoing_insbytes + - (PT_BYTE < to_byte ? PT_BYTE : to_byte) + + combined_after_bytes)); if (combined_after_bytes) - move_gap_both (GPT + 1, GPT_BYTE + combined_after_bytes); + combine_bytes (from + inschars, from_byte + outgoing_insbytes, + combined_after_bytes); + + if (combined_before_bytes) + combine_bytes (from, from_byte, combined_before_bytes); + + if (outgoing_insbytes == 0) + evaporate_overlays (from); MODIFF++; UNGCPRO; - signal_after_change (from, nchars_del, adjusted_inschars); + signal_after_change (from, nchars_del, PT - from); } /* Delete characters in current buffer @@ -1629,6 +1652,7 @@ int from, from_byte, to, to_byte; { register int nbytes_del, nchars_del; + int combined_after_bytes; nchars_del = to - from; nbytes_del = to_byte - from_byte; @@ -1677,6 +1701,16 @@ if (Z - GPT < end_unchanged) end_unchanged = Z - GPT; + combined_after_bytes + = count_combining_before (GAP_END_ADDR, ZV_BYTE - GPT_BYTE, PT, PT_BYTE); + + if (combined_after_bytes) + move_gap_both (GPT + combined_after_bytes, + GPT_BYTE + combined_after_bytes); + + if (combined_after_bytes) + combine_bytes (PT, PT_BYTE, combined_after_bytes); + evaporate_overlays (from); signal_after_change (from, nchars_del, 0); }