+ {
+ /* If this discrepancy is because of code conversion,
+ we cannot use this method; giveup and try the other. */
+ if (same_at_end > same_at_start
+ && FETCH_BYTE (same_at_end - 1) >= 0200
+ && ! NILP (current_buffer->enable_multibyte_characters)
+ && (CODING_MAY_REQUIRE_DECODING (&coding)))
+ giveup_match_end = 1;
+ break;
+ }
+ }
+ immediate_quit = 0;
+
+ if (! giveup_match_end)
+ {
+ int temp;
+
+ /* We win! We can handle REPLACE the optimized way. */
+
+ /* Extends the end of non-matching text area to multibyte
+ character boundary. */
+ if (! NILP (current_buffer->enable_multibyte_characters))
+ while (same_at_end < ZV_BYTE
+ && ! CHAR_HEAD_P (FETCH_BYTE (same_at_end)))
+ same_at_end++;
+
+ /* Don't try to reuse the same piece of text twice. */
+ overlap = (same_at_start - BEGV_BYTE
+ - (same_at_end + st.st_size - ZV));
+ if (overlap > 0)
+ same_at_end += overlap;
+
+ /* Arrange to read only the nonmatching middle part of the file. */
+ XSETFASTINT (beg, XINT (beg) + (same_at_start - BEGV_BYTE));
+ XSETFASTINT (end, XINT (end) - (ZV_BYTE - same_at_end));
+
+ del_range_byte (same_at_start, same_at_end, 0);
+ /* Insert from the file at the proper position. */
+ temp = BYTE_TO_CHAR (same_at_start);
+ SET_PT_BOTH (temp, same_at_start);
+
+ /* If display currently starts at beginning of line,
+ keep it that way. */
+ if (XBUFFER (XWINDOW (selected_window)->buffer) == current_buffer)
+ XWINDOW (selected_window)->start_at_line_beg = Fbolp ();
+
+ replace_handled = 1;
+ }
+ }
+
+ /* If requested, replace the accessible part of the buffer
+ with the file contents. Avoid replacing text at the
+ beginning or end of the buffer that matches the file contents;
+ that preserves markers pointing to the unchanged parts.
+
+ Here we implement this feature for the case where code conversion
+ is needed, in a simple way that needs a lot of memory.
+ The preceding if-statement handles the case of no conversion
+ in a more optimized way. */
+ if (!NILP (replace) && ! replace_handled)
+ {
+ int same_at_start = BEGV_BYTE;
+ int same_at_end = ZV_BYTE;
+ int overlap;
+ int bufpos;
+ /* Make sure that the gap is large enough. */
+ int bufsize = 2 * st.st_size;
+ unsigned char *conversion_buffer = (unsigned char *) xmalloc (bufsize);
+ int temp;
+
+ /* First read the whole file, performing code conversion into
+ CONVERSION_BUFFER. */
+
+ if (lseek (fd, XINT (beg), 0) < 0)
+ {
+ free (conversion_buffer);
+ report_file_error ("Setting file position",
+ Fcons (orig_filename, Qnil));
+ }
+
+ total = st.st_size; /* Total bytes in the file. */
+ how_much = 0; /* Bytes read from file so far. */
+ inserted = 0; /* Bytes put into CONVERSION_BUFFER so far. */
+ unprocessed = 0; /* Bytes not processed in previous loop. */
+
+ while (how_much < total)
+ {
+ /* try is reserved in some compilers (Microsoft C) */
+ int trytry = min (total - how_much, READ_BUF_SIZE - unprocessed);
+ char *destination = read_buf + unprocessed;
+ int this;
+
+ /* Allow quitting out of the actual I/O. */
+ immediate_quit = 1;
+ QUIT;
+ this = read (fd, destination, trytry);
+ immediate_quit = 0;
+
+ if (this < 0 || this + unprocessed == 0)
+ {
+ how_much = this;
+ break;
+ }
+
+ how_much += this;
+
+ if (CODING_MAY_REQUIRE_DECODING (&coding))
+ {
+ int require, result;
+
+ this += unprocessed;
+
+ /* If we are using more space than estimated,
+ make CONVERSION_BUFFER bigger. */
+ require = decoding_buffer_size (&coding, this);
+ if (inserted + require + 2 * (total - how_much) > bufsize)
+ {
+ bufsize = inserted + require + 2 * (total - how_much);
+ conversion_buffer = (unsigned char *) xrealloc (conversion_buffer, bufsize);
+ }
+
+ /* Convert this batch with results in CONVERSION_BUFFER. */
+ if (how_much >= total) /* This is the last block. */
+ coding.mode |= CODING_MODE_LAST_BLOCK;
+ result = decode_coding (&coding, read_buf,
+ conversion_buffer + inserted,
+ this, bufsize - inserted);
+
+ /* Save for next iteration whatever we didn't convert. */
+ unprocessed = this - coding.consumed;
+ bcopy (read_buf + coding.consumed, read_buf, unprocessed);
+ this = coding.produced;
+ }
+
+ inserted += this;
+ }
+
+ /* At this point, INSERTED is how many characters (i.e. bytes)
+ are present in CONVERSION_BUFFER.
+ HOW_MUCH should equal TOTAL,
+ or should be <= 0 if we couldn't read the file. */
+
+ if (how_much < 0)
+ {
+ free (conversion_buffer);
+
+ if (how_much == -1)
+ error ("IO error reading %s: %s",
+ XSTRING (orig_filename)->data, strerror (errno));
+ else if (how_much == -2)
+ error ("maximum buffer size exceeded");
+ }
+
+ /* Compare the beginning of the converted file
+ with the buffer text. */
+
+ bufpos = 0;
+ while (bufpos < inserted && same_at_start < same_at_end
+ && FETCH_BYTE (same_at_start) == conversion_buffer[bufpos])
+ same_at_start++, bufpos++;
+
+ /* If the file matches the buffer completely,
+ there's no need to replace anything. */
+
+ if (bufpos == inserted)
+ {
+ free (conversion_buffer);
+ close (fd);
+ specpdl_ptr--;
+ /* Truncate the buffer to the size of the file. */
+ del_range_1 (same_at_start, same_at_end, 0);
+ goto handled;