Mercurial > hg > xemacs-beta
diff src/insdel.c @ 98:0d2f883870bc r20-1b1
Import from CVS: tag r20-1b1
author | cvs |
---|---|
date | Mon, 13 Aug 2007 09:13:56 +0200 |
parents | 131b0175ea99 |
children | 8619ce7e4c50 |
line wrap: on
line diff
--- a/src/insdel.c Mon Aug 13 09:12:43 2007 +0200 +++ b/src/insdel.c Mon Aug 13 09:13:56 2007 +0200 @@ -232,10 +232,12 @@ /* Gap size. */ #define BUF_GAP_SIZE(buf) ((buf)->text->gap_size + 0) - +#define BUF_END_GAP_SIZE(buf) ((buf)->text->end_gap_size + 0) /* Set gap size. */ #define SET_BUF_GAP_SIZE(buf, value) \ do { (buf)->text->gap_size = (value); } while (0) +#define SET_BUF_END_GAP_SIZE(buf, value) \ + do { (buf)->text->end_gap_size = (value); } while (0) /* Gap location. */ #define BI_BUF_GPT(buf) ((buf)->text->gpt + 0) @@ -1801,6 +1803,15 @@ sledgehammer_extent_check (make_buffer (buf)); #endif } + if (pos == BI_BUF_Z (buf)) + { + /* merge gap with end gap */ + + SET_BUF_GAP_SIZE (buf, BUF_GAP_SIZE (buf) + BUF_END_GAP_SIZE (buf)); + SET_BUF_END_GAP_SIZE (buf, 0); + SET_END_SENTINEL (buf); + } + QUIT; } @@ -1818,6 +1829,49 @@ gap_right (buf, pos); } +/* Merge the end gap into the gap */ + +static void +merge_gap_with_end_gap (struct buffer *buf) +{ + Lisp_Object tem; + Bytind real_gap_loc; + Bytecount old_gap_size; + Bytecount increment; + + increment = BUF_END_GAP_SIZE (buf); + SET_BUF_END_GAP_SIZE (buf, 0); + + if (increment > 0) + { + /* Prevent quitting in move_gap. */ + tem = Vinhibit_quit; + Vinhibit_quit = Qt; + + real_gap_loc = BI_BUF_GPT (buf); + old_gap_size = BUF_GAP_SIZE (buf); + + /* Pretend the end gap is the gap */ + SET_BI_BUF_GPT (buf, BI_BUF_Z (buf) + BUF_GAP_SIZE (buf)); + SET_BUF_GAP_SIZE (buf, increment); + + /* Move the new gap down to be consecutive with the end of the old one. + This adjusts the markers properly too. */ + gap_left (buf, real_gap_loc + old_gap_size); + + /* Now combine the two into one large gap. */ + SET_BUF_GAP_SIZE (buf, BUF_GAP_SIZE (buf) + old_gap_size); + SET_BI_BUF_GPT (buf, real_gap_loc); + SET_GAP_SENTINEL (buf); + + /* We changed the total size of the buffer (including gap), + so we need to fix up the end sentinel. */ + SET_END_SENTINEL (buf); + + Vinhibit_quit = tem; + } +} + /* Make the gap INCREMENT bytes longer. */ static void @@ -1832,22 +1886,28 @@ a geometric progession that saves on realloc space. */ increment += 2000 + ((BI_BUF_Z (buf) - BI_BUF_BEG (buf)) / 8); - /* Don't allow a buffer size that won't fit in an int - even if it will fit in a Lisp integer. - That won't work because so many places use `int'. */ - - if (BUF_Z (buf) - BUF_BEG (buf) + BUF_GAP_SIZE (buf) + increment - >= ((unsigned) 1 << (min (INTBITS, VALBITS) - 1))) - error ("Buffer exceeds maximum size"); - - result = BUFFER_REALLOC (buf->text->beg, - BI_BUF_Z (buf) - BI_BUF_BEG (buf) + - BUF_GAP_SIZE (buf) + increment + - BUF_END_SENTINEL_SIZE); - if (result == 0) - memory_full (); - SET_BUF_BEG_ADDR (buf, result); - + if (increment > BUF_END_GAP_SIZE (buf)) + { + /* Don't allow a buffer size that won't fit in an int + even if it will fit in a Lisp integer. + That won't work because so many places use `int'. */ + + if (BUF_Z (buf) - BUF_BEG (buf) + BUF_GAP_SIZE (buf) + increment + >= ((unsigned) 1 << (min (INTBITS, VALBITS) - 1))) + error ("Buffer exceeds maximum size"); + + result = BUFFER_REALLOC (buf->text->beg, + BI_BUF_Z (buf) - BI_BUF_BEG (buf) + + BUF_GAP_SIZE (buf) + increment + + BUF_END_SENTINEL_SIZE); + if (result == 0) + memory_full (); + + SET_BUF_BEG_ADDR (buf, result); + } + else + increment = BUF_END_GAP_SIZE (buf); + /* Prevent quitting in move_gap. */ tem = Vinhibit_quit; Vinhibit_quit = Qt; @@ -1859,6 +1919,8 @@ SET_BI_BUF_GPT (buf, BI_BUF_Z (buf) + BUF_GAP_SIZE (buf)); SET_BUF_GAP_SIZE (buf, increment); + SET_BUF_END_GAP_SIZE (buf, 0); + /* Move the new gap down to be consecutive with the end of the old one. This adjusts the markers properly too. */ gap_left (buf, real_gap_loc + old_gap_size); @@ -2375,7 +2437,12 @@ in Emacs. */ move_gap (buf, ind); /* may QUIT */ if (! GAP_CAN_HOLD_SIZE_P (buf, length)) - make_gap (buf, length - BUF_GAP_SIZE (buf)); + { + if (BUF_END_GAP_SIZE (buf) >= length) + merge_gap_with_end_gap (buf); + else + make_gap (buf, length - BUF_GAP_SIZE (buf)); + } record_insert (buf, pos, cclen); BUF_MODIFF (buf)++; @@ -2564,50 +2631,96 @@ bi_to = bufpos_to_bytind (buf, to); bc_numdel = bi_to - bi_from; - /* Make sure the gap is somewhere in or next to what we are deleting. */ - if (bi_to < BI_BUF_GPT (buf)) - gap_left (buf, bi_to); - if (bi_from > BI_BUF_GPT (buf)) - gap_right (buf, bi_from); - - record_delete (buf, from, numdel); - BUF_MODIFF (buf)++; - MARK_BUFFERS_CHANGED; - - /* Relocate point as if it were a marker. */ - if (bi_from < BI_BUF_PT (buf)) + if (to == BUF_Z (buf) && + bi_from > BI_BUF_GPT (buf)) { - if (BI_BUF_PT (buf) < bi_to) - JUST_SET_POINT (buf, from, bi_from); - else - JUST_SET_POINT (buf, BUF_PT (buf) - numdel, - BI_BUF_PT (buf) - bc_numdel); + /* avoid moving the gap just to delete from the bottom. */ + + record_delete (buf, from, numdel); + BUF_MODIFF (buf)++; + MARK_BUFFERS_CHANGED; + + /* Relocate point as if it were a marker. */ + if (bi_from < BI_BUF_PT (buf)) + { + if (BI_BUF_PT (buf) < bi_to) + JUST_SET_POINT (buf, from, bi_from); + else + JUST_SET_POINT (buf, BUF_PT (buf) - numdel, + BI_BUF_PT (buf) - bc_numdel); + } + + /* Detach any extents that are completely within the range [FROM, TO], + if the extents are detachable. + + This must come AFTER record_delete(), so that the appropriate extents + will be present to be recorded, and BEFORE the gap size is increased, + as otherwise we will be confused about where the extents end. */ + process_extents_for_deletion (bufobj, bi_from, bi_to, 0); + + /* Relocate all markers pointing into the new, larger gap + to point at the end of the text before the gap. */ + adjust_markers (buf, + (bi_to + BUF_GAP_SIZE (buf)), + (bi_to + BUF_GAP_SIZE (buf)), + (- bc_numdel)); + + /* Relocate any extent endpoints just like markers. */ + adjust_extents_for_deletion (bufobj, bi_from, bi_to, + BUF_GAP_SIZE (buf), bc_numdel, 0); + SET_BUF_END_GAP_SIZE (buf, BUF_END_GAP_SIZE (buf) + bc_numdel); + + SET_BOTH_BUF_ZV (buf, BUF_ZV (buf) - numdel, BI_BUF_ZV (buf) - bc_numdel); + SET_BOTH_BUF_Z (buf, BUF_Z (buf) - numdel, BI_BUF_Z (buf) - bc_numdel); + SET_GAP_SENTINEL (buf); } - - /* Detach any extents that are completely within the range [FROM, TO], - if the extents are detachable. - - This must come AFTER record_delete(), so that the appropriate extents - will be present to be recorded, and BEFORE the gap size is increased, - as otherwise we will be confused about where the extents end. */ - process_extents_for_deletion (bufobj, bi_from, bi_to, 0); - - /* Relocate all markers pointing into the new, larger gap - to point at the end of the text before the gap. */ - adjust_markers (buf, - (bi_to + BUF_GAP_SIZE (buf)), - (bi_to + BUF_GAP_SIZE (buf)), - (- bc_numdel - BUF_GAP_SIZE (buf))); - - /* Relocate any extent endpoints just like markers. */ - adjust_extents_for_deletion (bufobj, bi_from, bi_to, BUF_GAP_SIZE (buf), - bc_numdel); - - SET_BUF_GAP_SIZE (buf, BUF_GAP_SIZE (buf) + bc_numdel); - SET_BOTH_BUF_ZV (buf, BUF_ZV (buf) - numdel, BI_BUF_ZV (buf) - bc_numdel); - SET_BOTH_BUF_Z (buf, BUF_Z (buf) - numdel, BI_BUF_Z (buf) - bc_numdel); - SET_BI_BUF_GPT (buf, bi_from); - SET_GAP_SENTINEL (buf); + else + { + /* Make sure the gap is somewhere in or next to what we are deleting. */ + if (bi_to < BI_BUF_GPT (buf)) + gap_left (buf, bi_to); + if (bi_from > BI_BUF_GPT (buf)) + gap_right (buf, bi_from); + + record_delete (buf, from, numdel); + BUF_MODIFF (buf)++; + MARK_BUFFERS_CHANGED; + + /* Relocate point as if it were a marker. */ + if (bi_from < BI_BUF_PT (buf)) + { + if (BI_BUF_PT (buf) < bi_to) + JUST_SET_POINT (buf, from, bi_from); + else + JUST_SET_POINT (buf, BUF_PT (buf) - numdel, + BI_BUF_PT (buf) - bc_numdel); + } + + /* Detach any extents that are completely within the range [FROM, TO], + if the extents are detachable. + + This must come AFTER record_delete(), so that the appropriate extents + will be present to be recorded, and BEFORE the gap size is increased, + as otherwise we will be confused about where the extents end. */ + process_extents_for_deletion (bufobj, bi_from, bi_to, 0); + + /* Relocate all markers pointing into the new, larger gap + to point at the end of the text before the gap. */ + adjust_markers (buf, + (bi_to + BUF_GAP_SIZE (buf)), + (bi_to + BUF_GAP_SIZE (buf)), + (- bc_numdel - BUF_GAP_SIZE (buf))); + + /* Relocate any extent endpoints just like markers. */ + adjust_extents_for_deletion (bufobj, bi_from, bi_to, BUF_GAP_SIZE (buf), + bc_numdel, BUF_GAP_SIZE (buf)); + + SET_BUF_GAP_SIZE (buf, BUF_GAP_SIZE (buf) + bc_numdel); + SET_BOTH_BUF_ZV (buf, BUF_ZV (buf) - numdel, BI_BUF_ZV (buf) - bc_numdel); + SET_BOTH_BUF_Z (buf, BUF_Z (buf) - numdel, BI_BUF_Z (buf) - bc_numdel); + SET_BI_BUF_GPT (buf, bi_from); + SET_GAP_SENTINEL (buf); + } #ifdef MULE buffer_mule_signal_deleted_region (buf, from, to, bi_from, bi_to); @@ -2957,7 +3070,8 @@ BUF_GAP_SIZE (b) + BUF_END_SENTINEL_SIZE); if (! BUF_BEG_ADDR (b)) memory_full (); - + + SET_BUF_END_GAP_SIZE (b, 0); SET_BI_BUF_GPT (b, 1); SET_BOTH_BUF_Z (b, 1, 1); SET_GAP_SENTINEL (b);