aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorRichard M. Stallman1997-04-02 05:03:06 +0000
committerRichard M. Stallman1997-04-02 05:03:06 +0000
commit727a0b4a0f92e32aa57f5c1567a6ec7993e4d610 (patch)
treeb09b17098bb9d4c68feba4e855b8c2d0209d0f18 /src
parent0118dcd34323b01bb6472298df0741030eceb8a4 (diff)
downloademacs-727a0b4a0f92e32aa57f5c1567a6ec7993e4d610.tar.gz
emacs-727a0b4a0f92e32aa57f5c1567a6ec7993e4d610.zip
(Finsert_file_contents): When handling REPLACE,
first try comparing block by block; if we discover a need for nontrivial code conversion, give up and try convert-whole-file method.
Diffstat (limited to 'src')
-rw-r--r--src/fileio.c132
1 files changed, 77 insertions, 55 deletions
diff --git a/src/fileio.c b/src/fileio.c
index 3e39154e6fa..65219833360 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -3034,6 +3034,7 @@ This does code conversion according to the value of\n\
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 unsigned char buffer[1 << 14];
3037 int replace_handled = 0;
3037 3038
3038 if (current_buffer->base_buffer && ! NILP (visit)) 3039 if (current_buffer->base_buffer && ! NILP (visit))
3039 error ("Cannot do file visiting in an indirect buffer"); 3040 error ("Cannot do file visiting in an indirect buffer");
@@ -3142,37 +3143,6 @@ This does code conversion according to the value of\n\
3142 error ("maximum buffer size exceeded"); 3143 error ("maximum buffer size exceeded");
3143 } 3144 }
3144 3145
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
3176 /* If requested, replace the accessible part of the buffer 3146 /* If requested, replace the accessible part of the buffer
3177 with the file contents. Avoid replacing text at the 3147 with the file contents. Avoid replacing text at the
3178 beginning or end of the buffer that matches the file contents; 3148 beginning or end of the buffer that matches the file contents;
@@ -3181,16 +3151,25 @@ This does code conversion according to the value of\n\
3181 Here we implement this feature in an optimized way 3151 Here we implement this feature in an optimized way
3182 for the case where code conversion is NOT needed. 3152 for the case where code conversion is NOT needed.
3183 The following if-statement handles the case of conversion 3153 The following if-statement handles the case of conversion
3184 in a less optimal way. */ 3154 in a less optimal way.
3155
3156 If the code conversion is "automatic" then we try using this
3157 method and hope for the best.
3158 But if we discover the need for conversion, we give up on this method
3159 and let the following if-statement handle the replace job. */
3185 if (!NILP (replace) 3160 if (!NILP (replace)
3186 && ! CODING_REQUIRE_CONVERSION (&coding)) 3161 && (! CODING_REQUIRE_CONVERSION (&coding)
3162 || (coding.type == coding_type_automatic
3163 && ! CODING_REQUIRE_TEXT_CONVERSION (&coding))
3164 || (coding.eol_type == CODING_EOL_AUTOMATIC
3165 && ! CODING_REQUIRE_EOL_CONVERSION (&coding))))
3187 { 3166 {
3188 int same_at_start = BEGV; 3167 int same_at_start = BEGV;
3189 int same_at_end = ZV; 3168 int same_at_end = ZV;
3190 int overlap; 3169 int overlap;
3191 /* There is still a possibility we will find the need to do code 3170 /* There is still a possibility we will find the need to do code
3192 conversion. If that happens, we set this variable to 1 to 3171 conversion. If that happens, we set this variable to 1 to
3193 give up on the REPLACE feature. */ 3172 give up on handling REPLACE in the optimized way. */
3194 int giveup_match_end = 0; 3173 int giveup_match_end = 0;
3195 3174
3196 if (XINT (beg) != 0) 3175 if (XINT (beg) != 0)
@@ -3215,6 +3194,26 @@ This does code conversion according to the value of\n\
3215 else if (nread == 0) 3194 else if (nread == 0)
3216 break; 3195 break;
3217 3196
3197 if (coding.type == coding_type_automatic)
3198 detect_coding (&coding, buffer, nread);
3199 if (CODING_REQUIRE_TEXT_CONVERSION (&coding))
3200 /* We found that the file should be decoded somehow.
3201 Let's give up here. */
3202 {
3203 giveup_match_end = 1;
3204 break;
3205 }
3206
3207 if (coding.eol_type == CODING_EOL_AUTOMATIC)
3208 detect_eol (&coding, buffer, nread);
3209 if (CODING_REQUIRE_EOL_CONVERSION (&coding))
3210 /* We found that the format of eol should be decoded.
3211 Let's give up here. */
3212 {
3213 giveup_match_end = 1;
3214 break;
3215 }
3216
3218 bufpos = 0; 3217 bufpos = 0;
3219 while (bufpos < nread && same_at_start < ZV 3218 while (bufpos < nread && same_at_start < ZV
3220 && FETCH_BYTE (same_at_start) == buffer[bufpos]) 3219 && FETCH_BYTE (same_at_start) == buffer[bufpos])
@@ -3272,30 +3271,46 @@ This does code conversion according to the value of\n\
3272 while (bufpos > 0 && same_at_end > same_at_start 3271 while (bufpos > 0 && same_at_end > same_at_start
3273 && FETCH_BYTE (same_at_end - 1) == buffer[bufpos - 1]) 3272 && FETCH_BYTE (same_at_end - 1) == buffer[bufpos - 1])
3274 same_at_end--, bufpos--; 3273 same_at_end--, bufpos--;
3274
3275 /* If we found a discrepancy, stop the scan. 3275 /* If we found a discrepancy, stop the scan.
3276 Otherwise loop around and scan the preceding bufferful. */ 3276 Otherwise loop around and scan the preceding bufferful. */
3277 if (bufpos != 0) 3277 if (bufpos != 0)
3278 break; 3278 {
3279 /* If this discrepancy is because of code conversion,
3280 we cannot use this method; giveup and try the other. */
3281 if (same_at_end > same_at_start
3282 && FETCH_BYTE (same_at_end - 1) >= 0200
3283 && ! NILP (current_buffer->enable_multibyte_characters))
3284 giveup_match_end = 1;
3285 break;
3286 }
3279 } 3287 }
3280 immediate_quit = 0; 3288 immediate_quit = 0;
3281 3289
3282 /* Don't try to reuse the same piece of text twice. */ 3290 if (! giveup_match_end)
3283 overlap = same_at_start - BEGV - (same_at_end + st.st_size - ZV); 3291 {
3284 if (overlap > 0) 3292 /* We win! We can handle REPLACE the optimized way. */
3285 same_at_end += overlap;
3286 3293
3287 /* Arrange to read only the nonmatching middle part of the file. */ 3294 /* Don't try to reuse the same piece of text twice. */
3288 XSETFASTINT (beg, XINT (beg) + (same_at_start - BEGV)); 3295 overlap = same_at_start - BEGV - (same_at_end + st.st_size - ZV);
3289 XSETFASTINT (end, XINT (end) - (ZV - same_at_end)); 3296 if (overlap > 0)
3297 same_at_end += overlap;
3290 3298
3291 del_range_1 (same_at_start, same_at_end, 0); 3299 /* Arrange to read only the nonmatching middle part of the file. */
3292 /* Insert from the file at the proper position. */ 3300 XSETFASTINT (beg, XINT (beg) + (same_at_start - BEGV));
3293 SET_PT (same_at_start); 3301 XSETFASTINT (end, XINT (end) - (ZV - same_at_end));
3294 3302
3295 /* If display currently starts at beginning of line, 3303 del_range_1 (same_at_start, same_at_end, 0);
3296 keep it that way. */ 3304 /* Insert from the file at the proper position. */
3297 if (XBUFFER (XWINDOW (selected_window)->buffer) == current_buffer) 3305 SET_PT (same_at_start);
3298 XWINDOW (selected_window)->start_at_line_beg = Fbolp (); 3306
3307 /* If display currently starts at beginning of line,
3308 keep it that way. */
3309 if (XBUFFER (XWINDOW (selected_window)->buffer) == current_buffer)
3310 XWINDOW (selected_window)->start_at_line_beg = Fbolp ();
3311
3312 replace_handled = 1;
3313 }
3299 } 3314 }
3300 3315
3301 /* If requested, replace the accessible part of the buffer 3316 /* If requested, replace the accessible part of the buffer
@@ -3307,7 +3322,7 @@ This does code conversion according to the value of\n\
3307 is needed, in a simple way that needs a lot of memory. 3322 is needed, in a simple way that needs a lot of memory.
3308 The preceding if-statement handles the case of no conversion 3323 The preceding if-statement handles the case of no conversion
3309 in a more optimized way. */ 3324 in a more optimized way. */
3310 if (!NILP (replace) && CODING_REQUIRE_CONVERSION (&coding)) 3325 if (!NILP (replace) && ! replace_handled)
3311 { 3326 {
3312 int same_at_start = BEGV; 3327 int same_at_start = BEGV;
3313 int same_at_end = ZV; 3328 int same_at_end = ZV;
@@ -3320,6 +3335,13 @@ This does code conversion according to the value of\n\
3320 /* First read the whole file, performing code conversion into 3335 /* First read the whole file, performing code conversion into
3321 CONVERSION_BUFFER. */ 3336 CONVERSION_BUFFER. */
3322 3337
3338 if (lseek (fd, XINT (beg), 0) < 0)
3339 {
3340 free (conversion_buffer);
3341 report_file_error ("Setting file position",
3342 Fcons (filename, Qnil));
3343 }
3344
3323 total = st.st_size; /* Total bytes in the file. */ 3345 total = st.st_size; /* Total bytes in the file. */
3324 how_much = 0; /* Bytes read from file so far. */ 3346 how_much = 0; /* Bytes read from file so far. */
3325 inserted = 0; /* Bytes put into CONVERSION_BUFFER so far. */ 3347 inserted = 0; /* Bytes put into CONVERSION_BUFFER so far. */
@@ -3430,23 +3452,23 @@ This does code conversion according to the value of\n\
3430 if (overlap > 0) 3452 if (overlap > 0)
3431 same_at_end += overlap; 3453 same_at_end += overlap;
3432 3454
3455 /* If display currently starts at beginning of line,
3456 keep it that way. */
3457 if (XBUFFER (XWINDOW (selected_window)->buffer) == current_buffer)
3458 XWINDOW (selected_window)->start_at_line_beg = Fbolp ();
3459
3433 /* Replace the chars that we need to replace, 3460 /* Replace the chars that we need to replace,
3434 and update INSERTED to equal the number of bytes 3461 and update INSERTED to equal the number of bytes
3435 we are taking from the file. */ 3462 we are taking from the file. */
3436 inserted -= (Z - same_at_end) + (same_at_start - BEG); 3463 inserted -= (Z - same_at_end) + (same_at_start - BEG);
3437 move_gap (same_at_start); 3464 move_gap (same_at_start);
3438 del_range_1 (same_at_start, same_at_end, 0); 3465 del_range_1 (same_at_start, same_at_end, 0);
3439 make_gap (inserted);
3440 insert (conversion_buffer + same_at_start - BEG, inserted); 3466 insert (conversion_buffer + same_at_start - BEG, inserted);
3441 3467
3442 free (conversion_buffer); 3468 free (conversion_buffer);
3443 close (fd); 3469 close (fd);
3444 specpdl_ptr--; 3470 specpdl_ptr--;
3445 3471
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; 3472 goto handled;
3451 } 3473 }
3452 3474