Mercurial > emacs
changeset 26982:3527c131b069
(Freplace_match): For nonliteral replacement,
construct all the new text first, then insert all at once.
author | Richard M. Stallman <rms@gnu.org> |
---|---|
date | Thu, 23 Dec 1999 04:45:26 +0000 |
parents | bf4bfaf9f594 |
children | cb23e1866bb7 |
files | src/search.c |
diffstat | 1 files changed, 53 insertions(+), 14 deletions(-) [+] |
line wrap: on
line diff
--- a/src/search.c Wed Dec 22 23:15:17 1999 +0000 +++ b/src/search.c Thu Dec 23 04:45:26 1999 +0000 @@ -2426,42 +2426,81 @@ Finsert_and_inherit (1, &newtext); else { - struct gcpro gcpro1; int length = STRING_BYTES (XSTRING (newtext)); + unsigned char *substed; + int substed_alloc_size, substed_len; - GCPRO1 (newtext); + substed_alloc_size = length * 2 + 100; + substed = (unsigned char *) xmalloc (substed_alloc_size + 1); + substed_len = 0; + + /* Go thru NEWTEXT, producing the actual text to insert in SUBSTED. */ for (pos_byte = 0, pos = 0; pos_byte < length;) { - int offset = PT - search_regs.start[sub]; + unsigned char str[MAX_MULTIBYTE_LENGTH]; + unsigned char *add_stuff; + int add_len; + int idx = -1; FETCH_STRING_CHAR_ADVANCE (c, newtext, pos, pos_byte); + /* Either set ADD_STUFF and ADD_LEN to the text to put in SUBSTED, + or set IDX to a match index, which means put that part + of the buffer text into SUBSTED. */ + if (c == '\\') { FETCH_STRING_CHAR_ADVANCE (c, newtext, pos, pos_byte); if (c == '&') - Finsert_buffer_substring - (Fcurrent_buffer (), - make_number (search_regs.start[sub] + offset), - make_number (search_regs.end[sub] + offset)); + idx = sub; else if (c >= '1' && c <= '9' && c <= search_regs.num_regs + '0') { if (search_regs.start[c - '0'] >= 1) - Finsert_buffer_substring - (Fcurrent_buffer (), - make_number (search_regs.start[c - '0'] + offset), - make_number (search_regs.end[c - '0'] + offset)); + idx = c - '0'; } else if (c == '\\') - insert_char (c); + add_len = 1, add_stuff = "\\"; else error ("Invalid use of `\\' in replacement text"); } else - insert_char (c); + { + add_len = CHAR_STRING (c, str); + add_stuff = str; + } + + /* If we want to copy part of a previous match, + set up ADD_STUFF and ADD_LEN to point to it. */ + if (idx >= 0) + { + int begbyte = CHAR_TO_BYTE (search_regs.start[idx]); + add_len = CHAR_TO_BYTE (search_regs.end[idx]) - begbyte; + if (search_regs.start[idx] < GPT && GPT < search_regs.end[idx]) + move_gap (search_regs.start[idx]); + add_stuff = BYTE_POS_ADDR (begbyte); + } + + /* Now the stuff we want to add to SUBSTED + is invariably ADD_LEN bytes starting at ADD_STUFF. */ + + /* Make sure SUBSTED is big enough. */ + if (substed_len + add_len >= substed_alloc_size) + { + substed_alloc_size = substed_len + add_len + 500; + substed = (unsigned char *) xrealloc (substed, + substed_alloc_size + 1); + } + + /* Now add to the end of SUBSTED. */ + bcopy (add_stuff, substed + substed_len, add_len); + substed_len += add_len; } - UNGCPRO; + + /* Now insert what we accumulated. */ + insert_and_inherit (substed, substed_len); + + xfree (substed); } inslen = PT - (search_regs.start[sub]);