aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorRichard M. Stallman1997-04-01 07:17:40 +0000
committerRichard M. Stallman1997-04-01 07:17:40 +0000
commit3dbcf3f67b2180d4c8aec76ad0298aaacad9dab0 (patch)
tree817c2d059493307dfa934f6efc3e323e6f2f9e4c /src
parent4f1d7d31737310082d0e03b0007d0c25db175480 (diff)
downloademacs-3dbcf3f67b2180d4c8aec76ad0298aaacad9dab0.tar.gz
emacs-3dbcf3f67b2180d4c8aec76ad0298aaacad9dab0.zip
(Finsert_file_contents): Determine the character coding
before we see if REPLACE can be handled. Do handle REPLACE even if code conversion is needed. (Fcopy_file): Fix previous change.
Diffstat (limited to 'src')
-rw-r--r--src/fileio.c233
1 files changed, 198 insertions, 35 deletions
diff --git a/src/fileio.c b/src/fileio.c
index cd8b0c19d0f..3e39154e6fa 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -2131,7 +2131,7 @@ A prefix arg makes KEEP-TIME non-nil.")
2131 if (set_file_times (XSTRING (newname)->data, atime, mtime)) 2131 if (set_file_times (XSTRING (newname)->data, atime, mtime))
2132 Fsignal (Qfile_date_error, 2132 Fsignal (Qfile_date_error,
2133 Fcons (build_string ("File already exists"), 2133 Fcons (build_string ("File already exists"),
2134 Fcons (absname, Qnil))); 2134 Fcons (newname, Qnil)));
2135 } 2135 }
2136#ifndef MSDOS 2136#ifndef MSDOS
2137 chmod (XSTRING (newname)->data, st.st_mode & 07777); 2137 chmod (XSTRING (newname)->data, st.st_mode & 07777);
@@ -3033,6 +3033,7 @@ This does code conversion according to the value of\n\
3033 int not_regular = 0; 3033 int not_regular = 0;
3034 char read_buf[READ_BUF_SIZE]; 3034 char read_buf[READ_BUF_SIZE];
3035 struct coding_system coding; 3035 struct coding_system coding;
3036 unsigned char buffer[1 << 14];
3036 3037
3037 if (current_buffer->base_buffer && ! NILP (visit)) 3038 if (current_buffer->base_buffer && ! NILP (visit))
3038 error ("Cannot do file visiting in an indirect buffer"); 3039 error ("Cannot do file visiting in an indirect buffer");
@@ -3141,20 +3142,49 @@ This does code conversion according to the value of\n\
3141 error ("maximum buffer size exceeded"); 3142 error ("maximum buffer size exceeded");
3142 } 3143 }
3143 3144
3145 /* Try to determine the character coding now,
3146 hoping we can recognize that no coding is used
3147 and thus enable the REPLACE feature to work. */
3148 if (!NILP (replace) && (coding.type == coding_type_automatic
3149 || coding.eol_type == CODING_EOL_AUTOMATIC))
3150 {
3151 int nread, bufpos;
3152
3153 nread = read (fd, buffer, sizeof buffer);
3154 if (nread < 0)
3155 error ("IO error reading %s: %s",
3156 XSTRING (filename)->data, strerror (errno));
3157 else if (nread > 0)
3158 {
3159 if (coding.type == coding_type_automatic)
3160 detect_coding (&coding, buffer, nread);
3161 if (coding.eol_type == CODING_EOL_AUTOMATIC)
3162 detect_eol (&coding, buffer, nread);
3163 if (lseek (fd, 0, 0) < 0)
3164 report_file_error ("Setting file position",
3165 Fcons (filename, Qnil));
3166 /* If we still haven't found anything other than
3167 "automatic", change to "no conversion"
3168 so that the replace feature will work. */
3169 if (coding.type == coding_type_automatic)
3170 coding.type = coding_type_no_conversion;
3171 if (coding.eol_type == CODING_EOL_AUTOMATIC)
3172 coding.eol_type = CODING_EOL_LF;
3173 }
3174 }
3175
3144 /* If requested, replace the accessible part of the buffer 3176 /* If requested, replace the accessible part of the buffer
3145 with the file contents. Avoid replacing text at the 3177 with the file contents. Avoid replacing text at the
3146 beginning or end of the buffer that matches the file contents; 3178 beginning or end of the buffer that matches the file contents;
3147 that preserves markers pointing to the unchanged parts. */ 3179 that preserves markers pointing to the unchanged parts.
3148 if (!NILP (replace) && CODING_REQUIRE_CONVERSION (&coding)) 3180
3149 { 3181 Here we implement this feature in an optimized way
3150 /* We have to decode the input, which means replace mode is 3182 for the case where code conversion is NOT needed.
3151 quite difficult. We give it up for the moment. */ 3183 The following if-statement handles the case of conversion
3152 replace = Qnil; 3184 in a less optimal way. */
3153 del_range_1 (BEGV, ZV, 0); 3185 if (!NILP (replace)
3154 } 3186 && ! CODING_REQUIRE_CONVERSION (&coding))
3155 if (!NILP (replace))
3156 { 3187 {
3157 unsigned char buffer[1 << 14];
3158 int same_at_start = BEGV; 3188 int same_at_start = BEGV;
3159 int same_at_end = ZV; 3189 int same_at_end = ZV;
3160 int overlap; 3190 int overlap;
@@ -3185,26 +3215,6 @@ This does code conversion according to the value of\n\
3185 else if (nread == 0) 3215 else if (nread == 0)
3186 break; 3216 break;
3187 3217
3188 if (coding.type == coding_type_automatic)
3189 detect_coding (&coding, buffer, nread);
3190 if (CODING_REQUIRE_TEXT_CONVERSION (&coding))
3191 /* We found that the file should be decoded somehow.
3192 Let's give up here. */
3193 {
3194 giveup_match_end = 1;
3195 break;
3196 }
3197
3198 if (coding.eol_type == CODING_EOL_AUTOMATIC)
3199 detect_eol (&coding, buffer, nread);
3200 if (CODING_REQUIRE_EOL_CONVERSION (&coding))
3201 /* We found that the format of eol should be decoded.
3202 Let's give up here. */
3203 {
3204 giveup_match_end = 1;
3205 break;
3206 }
3207
3208 bufpos = 0; 3218 bufpos = 0;
3209 while (bufpos < nread && same_at_start < ZV 3219 while (bufpos < nread && same_at_start < ZV
3210 && FETCH_BYTE (same_at_start) == buffer[bufpos]) 3220 && FETCH_BYTE (same_at_start) == buffer[bufpos])
@@ -3266,10 +3276,6 @@ This does code conversion according to the value of\n\
3266 Otherwise loop around and scan the preceding bufferful. */ 3276 Otherwise loop around and scan the preceding bufferful. */
3267 if (bufpos != 0) 3277 if (bufpos != 0)
3268 break; 3278 break;
3269 /* If display current starts at beginning of line,
3270 keep it that way. */
3271 if (XBUFFER (XWINDOW (selected_window)->buffer) == current_buffer)
3272 XWINDOW (selected_window)->start_at_line_beg = Fbolp ();
3273 } 3279 }
3274 immediate_quit = 0; 3280 immediate_quit = 0;
3275 3281
@@ -3285,6 +3291,163 @@ This does code conversion according to the value of\n\
3285 del_range_1 (same_at_start, same_at_end, 0); 3291 del_range_1 (same_at_start, same_at_end, 0);
3286 /* Insert from the file at the proper position. */ 3292 /* Insert from the file at the proper position. */
3287 SET_PT (same_at_start); 3293 SET_PT (same_at_start);
3294
3295 /* If display currently starts at beginning of line,
3296 keep it that way. */
3297 if (XBUFFER (XWINDOW (selected_window)->buffer) == current_buffer)
3298 XWINDOW (selected_window)->start_at_line_beg = Fbolp ();
3299 }
3300
3301 /* If requested, replace the accessible part of the buffer
3302 with the file contents. Avoid replacing text at the
3303 beginning or end of the buffer that matches the file contents;
3304 that preserves markers pointing to the unchanged parts.
3305
3306 Here we implement this feature for the case where code conversion
3307 is needed, in a simple way that needs a lot of memory.
3308 The preceding if-statement handles the case of no conversion
3309 in a more optimized way. */
3310 if (!NILP (replace) && CODING_REQUIRE_CONVERSION (&coding))
3311 {
3312 int same_at_start = BEGV;
3313 int same_at_end = ZV;
3314 int overlap;
3315 int bufpos;
3316 /* Make sure that the gap is large enough. */
3317 int bufsize = 2 * st.st_size;
3318 unsigned char *conversion_buffer = (unsigned char *) malloc (bufsize);
3319
3320 /* First read the whole file, performing code conversion into
3321 CONVERSION_BUFFER. */
3322
3323 total = st.st_size; /* Total bytes in the file. */
3324 how_much = 0; /* Bytes read from file so far. */
3325 inserted = 0; /* Bytes put into CONVERSION_BUFFER so far. */
3326 unprocessed = 0; /* Bytes not processed in previous loop. */
3327
3328 while (how_much < total)
3329 {
3330 /* try is reserved in some compilers (Microsoft C) */
3331 int trytry = min (total - how_much, READ_BUF_SIZE - unprocessed);
3332 char *destination = read_buf + unprocessed;
3333 int this;
3334
3335 /* Allow quitting out of the actual I/O. */
3336 immediate_quit = 1;
3337 QUIT;
3338 this = read (fd, destination, trytry);
3339 immediate_quit = 0;
3340
3341 if (this < 0 || this + unprocessed == 0)
3342 {
3343 how_much = this;
3344 break;
3345 }
3346
3347 how_much += this;
3348
3349 if (CODING_REQUIRE_CONVERSION (&coding))
3350 {
3351 int require, produced, consumed;
3352
3353 this += unprocessed;
3354
3355 /* If we are using more space than estimated,
3356 make CONVERSION_BUFFER bigger. */
3357 require = decoding_buffer_size (&coding, this);
3358 if (inserted + require + 2 * (total - how_much) > bufsize)
3359 {
3360 bufsize = inserted + require + 2 * (total - how_much);
3361 conversion_buffer = (unsigned char *) realloc (conversion_buffer, bufsize);
3362 }
3363
3364 /* Convert this batch with results in CONVERSION_BUFFER. */
3365 if (how_much >= total) /* This is the last block. */
3366 coding.last_block = 1;
3367 produced = decode_coding (&coding, read_buf,
3368 conversion_buffer + inserted,
3369 this, bufsize - inserted,
3370 &consumed);
3371
3372 /* Save for next iteration whatever we didn't convert. */
3373 unprocessed = this - consumed;
3374 bcopy (read_buf + consumed, read_buf, unprocessed);
3375 this = produced;
3376 }
3377
3378 inserted += this;
3379 }
3380
3381 /* At this point, INSERTED is how many characters
3382 are present in CONVERSION_BUFFER.
3383 HOW_MUCH should equal TOTAL,
3384 or should be <= 0 if we couldn't read the file. */
3385
3386 if (how_much < 0)
3387 {
3388 free (conversion_buffer);
3389
3390 if (how_much == -1)
3391 error ("IO error reading %s: %s",
3392 XSTRING (filename)->data, strerror (errno));
3393 else if (how_much == -2)
3394 error ("maximum buffer size exceeded");
3395 }
3396
3397 /* Compare the beginning of the converted file
3398 with the buffer text. */
3399
3400 bufpos = 0;
3401 while (bufpos < inserted && same_at_start < same_at_end
3402 && FETCH_BYTE (same_at_start) == conversion_buffer[bufpos])
3403 same_at_start++, bufpos++;
3404
3405 /* If the file matches the buffer completely,
3406 there's no need to replace anything. */
3407
3408 if (bufpos == inserted)
3409 {
3410 free (conversion_buffer);
3411 close (fd);
3412 specpdl_ptr--;
3413 /* Truncate the buffer to the size of the file. */
3414 del_range_1 (same_at_start, same_at_end, 0);
3415 goto handled;
3416 }
3417
3418 /* Scan this bufferful from the end, comparing with
3419 the Emacs buffer. */
3420 bufpos = inserted;
3421
3422 /* Compare with same_at_start to avoid counting some buffer text
3423 as matching both at the file's beginning and at the end. */
3424 while (bufpos > 0 && same_at_end > same_at_start
3425 && FETCH_BYTE (same_at_end - 1) == conversion_buffer[bufpos - 1])
3426 same_at_end--, bufpos--;
3427
3428 /* Don't try to reuse the same piece of text twice. */
3429 overlap = same_at_start - BEGV - (same_at_end + inserted - ZV);
3430 if (overlap > 0)
3431 same_at_end += overlap;
3432
3433 /* Replace the chars that we need to replace,
3434 and update INSERTED to equal the number of bytes
3435 we are taking from the file. */
3436 inserted -= (Z - same_at_end) + (same_at_start - BEG);
3437 move_gap (same_at_start);
3438 del_range_1 (same_at_start, same_at_end, 0);
3439 make_gap (inserted);
3440 insert (conversion_buffer + same_at_start - BEG, inserted);
3441
3442 free (conversion_buffer);
3443 close (fd);
3444 specpdl_ptr--;
3445
3446 /* If display currently starts at beginning of line,
3447 keep it that way. */
3448 if (XBUFFER (XWINDOW (selected_window)->buffer) == current_buffer)
3449 XWINDOW (selected_window)->start_at_line_beg = Fbolp ();
3450 goto handled;
3288 } 3451 }
3289 3452
3290 total = XINT (end) - XINT (beg); 3453 total = XINT (end) - XINT (beg);