aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorRichard M. Stallman1997-12-31 22:16:35 +0000
committerRichard M. Stallman1997-12-31 22:16:35 +0000
commitec7adf2664746ff3bb20c012f685451b9607ef42 (patch)
tree57e1ff957b06d1c858ee9daa473b4c2922a8de1d /src
parenta9c26562b3d0790b1dadf242d8ad3b10bbafe381 (diff)
downloademacs-ec7adf2664746ff3bb20c012f685451b9607ef42.tar.gz
emacs-ec7adf2664746ff3bb20c012f685451b9607ef42.zip
(Finsert_file_contents): Update call to CHAR_HEAD_P.
(Fwrite_region): Use scan_newline. (restore_point_unwind): Now static. Use Fgoto_char. (Funhandled_file_name_directory): Doc fix. (Finsert_file_contents): Handle bytes vs chars. (Fwrite_region): Handle bytes vs chars. (a_write): Take args in bytes; handle annotations labeled in chars. (e_write): Rename args. (Funhandled_file_name_directory): Doc fix. (a_write, e_write): Now static.
Diffstat (limited to 'src')
-rw-r--r--src/fileio.c231
1 files changed, 124 insertions, 107 deletions
diff --git a/src/fileio.c b/src/fileio.c
index 2cf1693200c..4d477b19c8e 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -230,6 +230,10 @@ Lisp_Object Qfile_name_history;
230 230
231Lisp_Object Qcar_less_than_car; 231Lisp_Object Qcar_less_than_car;
232 232
233static int a_write P_ ((int, char *, int, int,
234 Lisp_Object, struct coding_system *));
235static int e_write P_ ((int, char *, int, struct coding_system *));
236
233void 237void
234report_file_error (string, data) 238report_file_error (string, data)
235 char *string; 239 char *string;
@@ -259,11 +263,11 @@ close_file_unwind (fd)
259 263
260/* Restore point, having saved it as a marker. */ 264/* Restore point, having saved it as a marker. */
261 265
262Lisp_Object 266static Lisp_Object
263restore_point_unwind (location) 267restore_point_unwind (location)
264 Lisp_Object location; 268 Lisp_Object location;
265{ 269{
266 SET_PT (marker_position (location)); 270 Fgoto_char (location);
267 Fset_marker (location, Qnil, Qnil); 271 Fset_marker (location, Qnil, Qnil);
268 return Qnil; 272 return Qnil;
269} 273}
@@ -449,7 +453,7 @@ DEFUN ("unhandled-file-name-directory", Funhandled_file_name_directory, Sunhandl
449A `directly usable' directory name is one that may be used without the\n\ 453A `directly usable' directory name is one that may be used without the\n\
450intervention of any file handler.\n\ 454intervention of any file handler.\n\
451If FILENAME is a directly usable file itself, return\n\ 455If FILENAME is a directly usable file itself, return\n\
452(file-name-directory FILENAME).\n\ 456\(file-name-directory FILENAME).\n\
453The `call-process' and `start-process' functions use this function to\n\ 457The `call-process' and `start-process' functions use this function to\n\
454get a current directory to run processes in.") 458get a current directory to run processes in.")
455 (filename) 459 (filename)
@@ -3076,13 +3080,14 @@ Lisp_Object Qfind_buffer_file_type;
3076DEFUN ("insert-file-contents", Finsert_file_contents, Sinsert_file_contents, 3080DEFUN ("insert-file-contents", Finsert_file_contents, Sinsert_file_contents,
3077 1, 5, 0, 3081 1, 5, 0,
3078 "Insert contents of file FILENAME after point.\n\ 3082 "Insert contents of file FILENAME after point.\n\
3079Returns list of absolute file name and length of data inserted.\n\ 3083Returns list of absolute file name and number of bytes inserted.\n\
3080If second argument VISIT is non-nil, the buffer's visited filename\n\ 3084If second argument VISIT is non-nil, the buffer's visited filename\n\
3081and last save file modtime are set, and it is marked unmodified.\n\ 3085and last save file modtime are set, and it is marked unmodified.\n\
3082If visiting and the file does not exist, visiting is completed\n\ 3086If visiting and the file does not exist, visiting is completed\n\
3083before the error is signaled.\n\ 3087before the error is signaled.\n\
3084The optional third and fourth arguments BEG and END\n\ 3088The optional third and fourth arguments BEG and END\n\
3085specify what portion of the file to insert.\n\ 3089specify what portion of the file to insert.\n\
3090These arguments count bytes in the file, not characters in the buffer.\n\
3086If VISIT is non-nil, BEG and END must be nil.\n\ 3091If VISIT is non-nil, BEG and END must be nil.\n\
3087\n\ 3092\n\
3088If optional fifth argument REPLACE is non-nil,\n\ 3093If optional fifth argument REPLACE is non-nil,\n\
@@ -3101,7 +3106,8 @@ This does code conversion according to the value of\n\
3101{ 3106{
3102 struct stat st; 3107 struct stat st;
3103 register int fd; 3108 register int fd;
3104 register int inserted = 0; 3109 int inserted = 0;
3110 int inserted_chars = 0;
3105 register int how_much; 3111 register int how_much;
3106 register int unprocessed; 3112 register int unprocessed;
3107 int count = specpdl_ptr - specpdl; 3113 int count = specpdl_ptr - specpdl;
@@ -3114,6 +3120,7 @@ This does code conversion according to the value of\n\
3114 struct coding_system coding; 3120 struct coding_system coding;
3115 unsigned char buffer[1 << 14]; 3121 unsigned char buffer[1 << 14];
3116 int replace_handled = 0; 3122 int replace_handled = 0;
3123 int set_coding_system = 0;
3117 3124
3118 if (current_buffer->base_buffer && ! NILP (visit)) 3125 if (current_buffer->base_buffer && ! NILP (visit))
3119 error ("Cannot do file visiting in an indirect buffer"); 3126 error ("Cannot do file visiting in an indirect buffer");
@@ -3291,8 +3298,11 @@ This does code conversion according to the value of\n\
3291 if (!NILP (replace) 3298 if (!NILP (replace)
3292 && ! CODING_REQUIRE_DECODING (&coding)) 3299 && ! CODING_REQUIRE_DECODING (&coding))
3293 { 3300 {
3294 int same_at_start = BEGV; 3301 /* same_at_start and same_at_end count bytes,
3295 int same_at_end = ZV; 3302 because file access counts bytes
3303 and BEG and END count bytes. */
3304 int same_at_start = BEGV_BYTE;
3305 int same_at_end = ZV_BYTE;
3296 int overlap; 3306 int overlap;
3297 /* There is still a possibility we will find the need to do code 3307 /* There is still a possibility we will find the need to do code
3298 conversion. If that happens, we set this variable to 1 to 3308 conversion. If that happens, we set this variable to 1 to
@@ -3343,7 +3353,7 @@ This does code conversion according to the value of\n\
3343 } 3353 }
3344 3354
3345 bufpos = 0; 3355 bufpos = 0;
3346 while (bufpos < nread && same_at_start < ZV 3356 while (bufpos < nread && same_at_start < ZV_BYTE
3347 && FETCH_BYTE (same_at_start) == buffer[bufpos]) 3357 && FETCH_BYTE (same_at_start) == buffer[bufpos])
3348 same_at_start++, bufpos++; 3358 same_at_start++, bufpos++;
3349 /* If we found a discrepancy, stop the scan. 3359 /* If we found a discrepancy, stop the scan.
@@ -3354,7 +3364,7 @@ This does code conversion according to the value of\n\
3354 immediate_quit = 0; 3364 immediate_quit = 0;
3355 /* If the file matches the buffer completely, 3365 /* If the file matches the buffer completely,
3356 there's no need to replace anything. */ 3366 there's no need to replace anything. */
3357 if (same_at_start - BEGV == XINT (end)) 3367 if (same_at_start - BEGV_BYTE == XINT (end))
3358 { 3368 {
3359 close (fd); 3369 close (fd);
3360 specpdl_ptr--; 3370 specpdl_ptr--;
@@ -3372,7 +3382,7 @@ This does code conversion according to the value of\n\
3372 int total_read, nread, bufpos, curpos, trial; 3382 int total_read, nread, bufpos, curpos, trial;
3373 3383
3374 /* At what file position are we now scanning? */ 3384 /* At what file position are we now scanning? */
3375 curpos = XINT (end) - (ZV - same_at_end); 3385 curpos = XINT (end) - (ZV_BYTE - same_at_end);
3376 /* If the entire file matches the buffer tail, stop the scan. */ 3386 /* If the entire file matches the buffer tail, stop the scan. */
3377 if (curpos == 0) 3387 if (curpos == 0)
3378 break; 3388 break;
@@ -3419,26 +3429,31 @@ This does code conversion according to the value of\n\
3419 3429
3420 if (! giveup_match_end) 3430 if (! giveup_match_end)
3421 { 3431 {
3432 int temp;
3433
3422 /* We win! We can handle REPLACE the optimized way. */ 3434 /* We win! We can handle REPLACE the optimized way. */
3423 3435
3424 /* Extends the end of non-matching text area to multibyte 3436 /* Extends the end of non-matching text area to multibyte
3425 character boundary. */ 3437 character boundary. */
3426 if (! NILP (current_buffer->enable_multibyte_characters)) 3438 if (! NILP (current_buffer->enable_multibyte_characters))
3427 while (same_at_end < ZV && ! CHAR_HEAD_P (POS_ADDR (same_at_end))) 3439 while (same_at_end < ZV_BYTE
3440 && ! CHAR_HEAD_P (FETCH_BYTE (same_at_end)))
3428 same_at_end++; 3441 same_at_end++;
3429 3442
3430 /* Don't try to reuse the same piece of text twice. */ 3443 /* Don't try to reuse the same piece of text twice. */
3431 overlap = same_at_start - BEGV - (same_at_end + st.st_size - ZV); 3444 overlap = (same_at_start - BEGV_BYTE
3445 - (same_at_end + st.st_size - ZV));
3432 if (overlap > 0) 3446 if (overlap > 0)
3433 same_at_end += overlap; 3447 same_at_end += overlap;
3434 3448
3435 /* Arrange to read only the nonmatching middle part of the file. */ 3449 /* Arrange to read only the nonmatching middle part of the file. */
3436 XSETFASTINT (beg, XINT (beg) + (same_at_start - BEGV)); 3450 XSETFASTINT (beg, XINT (beg) + (same_at_start - BEGV_BYTE));
3437 XSETFASTINT (end, XINT (end) - (ZV - same_at_end)); 3451 XSETFASTINT (end, XINT (end) - (ZV_BYTE - same_at_end));
3438 3452
3439 del_range_1 (same_at_start, same_at_end, 0); 3453 del_range_byte (same_at_start, same_at_end, 0);
3440 /* Insert from the file at the proper position. */ 3454 /* Insert from the file at the proper position. */
3441 SET_PT (same_at_start); 3455 temp = BYTE_TO_CHAR (same_at_start);
3456 SET_PT_BOTH (temp, same_at_start);
3442 3457
3443 /* If display currently starts at beginning of line, 3458 /* If display currently starts at beginning of line,
3444 keep it that way. */ 3459 keep it that way. */
@@ -3460,13 +3475,14 @@ This does code conversion according to the value of\n\
3460 in a more optimized way. */ 3475 in a more optimized way. */
3461 if (!NILP (replace) && ! replace_handled) 3476 if (!NILP (replace) && ! replace_handled)
3462 { 3477 {
3463 int same_at_start = BEGV; 3478 int same_at_start = BEGV_BYTE;
3464 int same_at_end = ZV; 3479 int same_at_end = ZV_BYTE;
3465 int overlap; 3480 int overlap;
3466 int bufpos; 3481 int bufpos;
3467 /* Make sure that the gap is large enough. */ 3482 /* Make sure that the gap is large enough. */
3468 int bufsize = 2 * st.st_size; 3483 int bufsize = 2 * st.st_size;
3469 unsigned char *conversion_buffer = (unsigned char *) xmalloc (bufsize); 3484 unsigned char *conversion_buffer = (unsigned char *) xmalloc (bufsize);
3485 int temp;
3470 3486
3471 /* First read the whole file, performing code conversion into 3487 /* First read the whole file, performing code conversion into
3472 CONVERSION_BUFFER. */ 3488 CONVERSION_BUFFER. */
@@ -3585,7 +3601,7 @@ This does code conversion according to the value of\n\
3585 same_at_end--, bufpos--; 3601 same_at_end--, bufpos--;
3586 3602
3587 /* Don't try to reuse the same piece of text twice. */ 3603 /* Don't try to reuse the same piece of text twice. */
3588 overlap = same_at_start - BEGV - (same_at_end + inserted - ZV); 3604 overlap = same_at_start - BEGV_BYTE - (same_at_end + inserted - ZV_BYTE);
3589 if (overlap > 0) 3605 if (overlap > 0)
3590 same_at_end += overlap; 3606 same_at_end += overlap;
3591 3607
@@ -3597,11 +3613,12 @@ This does code conversion according to the value of\n\
3597 /* Replace the chars that we need to replace, 3613 /* Replace the chars that we need to replace,
3598 and update INSERTED to equal the number of bytes 3614 and update INSERTED to equal the number of bytes
3599 we are taking from the file. */ 3615 we are taking from the file. */
3600 inserted -= (Z - same_at_end) + (same_at_start - BEG); 3616 inserted -= (Z_BYTE - same_at_end) + (same_at_start - BEG_BYTE);
3601 move_gap (same_at_start); 3617 del_range_byte (same_at_start, same_at_end, 0);
3602 del_range_1 (same_at_start, same_at_end, 0); 3618 SET_PT_BOTH (GPT, GPT_BYTE);
3603 SET_PT (same_at_start); 3619
3604 insert_1 (conversion_buffer + same_at_start - BEG, inserted, 0, 0); 3620 insert_1 (conversion_buffer + same_at_start - BEG_BYTE, inserted,
3621 0, 0, 0);
3605 3622
3606 free (conversion_buffer); 3623 free (conversion_buffer);
3607 close (fd); 3624 close (fd);
@@ -3653,9 +3670,9 @@ This does code conversion according to the value of\n\
3653 int trytry = min (total - how_much, READ_BUF_SIZE - unprocessed); 3670 int trytry = min (total - how_much, READ_BUF_SIZE - unprocessed);
3654 char *destination = (! (CODING_REQUIRE_DECODING (&coding) 3671 char *destination = (! (CODING_REQUIRE_DECODING (&coding)
3655 || CODING_REQUIRE_DETECTION (&coding)) 3672 || CODING_REQUIRE_DETECTION (&coding))
3656 ? (char *) (POS_ADDR (PT + inserted - 1) + 1) 3673 ? (char *) (BYTE_POS_ADDR (PT_BYTE + inserted - 1) + 1)
3657 : read_buf + unprocessed); 3674 : read_buf + unprocessed);
3658 int this; 3675 int this, this_chars;
3659 3676
3660 /* Allow quitting out of the actual I/O. */ 3677 /* Allow quitting out of the actual I/O. */
3661 immediate_quit = 1; 3678 immediate_quit = 1;
@@ -3677,6 +3694,7 @@ This does code conversion according to the value of\n\
3677 if (! not_regular) 3694 if (! not_regular)
3678 how_much += this; 3695 how_much += this;
3679 3696
3697 this_chars = this;
3680 if (CODING_REQUIRE_DECODING (&coding) 3698 if (CODING_REQUIRE_DECODING (&coding)
3681 || CODING_REQUIRE_DETECTION (&coding)) 3699 || CODING_REQUIRE_DETECTION (&coding))
3682 { 3700 {
@@ -3703,14 +3721,14 @@ This does code conversion according to the value of\n\
3703 } 3721 }
3704 3722
3705 produced = decode_coding (&coding, read_buf, 3723 produced = decode_coding (&coding, read_buf,
3706 POS_ADDR (PT + inserted - 1) + 1, 3724 BYTE_POS_ADDR (PT_BYTE + inserted - 1) + 1,
3707 this, GAP_SIZE, &consumed); 3725 this, GAP_SIZE, &consumed);
3708 if (produced > 0) 3726 if (produced > 0)
3709 { 3727 {
3710 Lisp_Object temp; 3728 Lisp_Object temp;
3711 3729
3712 XSET (temp, Lisp_Int, Z + produced); 3730 XSET (temp, Lisp_Int, Z_BYTE + produced);
3713 if (Z + produced != XINT (temp)) 3731 if (Z_BYTE + produced != XINT (temp))
3714 { 3732 {
3715 how_much = -2; 3733 how_much = -2;
3716 break; 3734 break;
@@ -3719,19 +3737,25 @@ This does code conversion according to the value of\n\
3719 unprocessed = this - consumed; 3737 unprocessed = this - consumed;
3720 bcopy (read_buf + consumed, read_buf, unprocessed); 3738 bcopy (read_buf + consumed, read_buf, unprocessed);
3721 this = produced; 3739 this = produced;
3740 this_chars = chars_in_text (BYTE_POS_ADDR (PT_BYTE + inserted - 1) + 1,
3741 produced);
3722 } 3742 }
3723 3743
3724 GPT += this;
3725 GAP_SIZE -= this; 3744 GAP_SIZE -= this;
3726 ZV += this; 3745 GPT_BYTE += this;
3727 Z += this; 3746 ZV_BYTE += this;
3747 Z_BYTE += this;
3748 GPT += this_chars;
3749 ZV += this_chars;
3750 Z += this_chars;
3751
3728 if (GAP_SIZE > 0) 3752 if (GAP_SIZE > 0)
3729 /* Put an anchor to ensure multi-byte form ends at gap. */ 3753 /* Put an anchor to ensure multi-byte form ends at gap. */
3730 *GPT_ADDR = 0; 3754 *GPT_ADDR = 0;
3731 inserted += this; 3755 inserted += this;
3756 inserted_chars += this_chars;
3732 } 3757 }
3733 3758
3734
3735#ifdef DOS_NT 3759#ifdef DOS_NT
3736 /* Use the conversion type to determine buffer-file-type 3760 /* Use the conversion type to determine buffer-file-type
3737 (find-buffer-file-type is now used to help determine the 3761 (find-buffer-file-type is now used to help determine the
@@ -3743,37 +3767,12 @@ This does code conversion according to the value of\n\
3743 current_buffer->buffer_file_type = Qt; 3767 current_buffer->buffer_file_type = Qt;
3744#endif 3768#endif
3745 3769
3746 /* We don't have to consider file type of MSDOS because all files
3747 are read as binary and end-of-line format has already been
3748 decoded appropriately. */
3749#if 0
3750#ifdef DOS_NT
3751 /* Demacs 1.1.1 91/10/16 HIRANO Satoshi, MW July 1993 */
3752 /* Determine file type from name and remove LFs from CR-LFs if the file
3753 is deemed to be a text file. */
3754 {
3755 current_buffer->buffer_file_type
3756 = call1 (Qfind_buffer_file_type, orig_filename);
3757 if (NILP (current_buffer->buffer_file_type))
3758 {
3759 int reduced_size
3760 = inserted - crlf_to_lf (inserted, POS_ADDR (PT - 1) + 1);
3761 ZV -= reduced_size;
3762 Z -= reduced_size;
3763 GPT -= reduced_size;
3764 GAP_SIZE += reduced_size;
3765 inserted -= reduced_size;
3766 }
3767 }
3768#endif /* DOS_NT */
3769#endif /* 0 */
3770
3771 if (inserted > 0) 3770 if (inserted > 0)
3772 { 3771 {
3773 record_insert (PT, inserted); 3772 record_insert (PT, inserted_chars);
3774 3773
3775 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */ 3774 /* Only defined if Emacs is compiled with USE_TEXT_PROPERTIES */
3776 offset_intervals (current_buffer, PT, inserted); 3775 offset_intervals (current_buffer, PT, inserted_chars);
3777 MODIFF++; 3776 MODIFF++;
3778 } 3777 }
3779 3778
@@ -3788,6 +3787,8 @@ This does code conversion according to the value of\n\
3788 else if (how_much == -2) 3787 else if (how_much == -2)
3789 error ("maximum buffer size exceeded"); 3788 error ("maximum buffer size exceeded");
3790 3789
3790 set_coding_system = 1;
3791
3791 notfound: 3792 notfound:
3792 handled: 3793 handled:
3793 3794
@@ -3827,22 +3828,23 @@ This does code conversion according to the value of\n\
3827 } 3828 }
3828 3829
3829 /* Decode file format */ 3830 /* Decode file format */
3830 if (inserted > 0) 3831 if (inserted_chars > 0)
3831 { 3832 {
3832 insval = call3 (Qformat_decode, 3833 insval = call3 (Qformat_decode,
3833 Qnil, make_number (inserted), visit); 3834 Qnil, make_number (inserted_chars), visit);
3834 CHECK_NUMBER (insval, 0); 3835 CHECK_NUMBER (insval, 0);
3835 inserted = XFASTINT (insval); 3836 inserted_chars = XFASTINT (insval);
3836 } 3837 }
3837 3838
3838 /* Call after-change hooks for the inserted text, aside from the case 3839 /* Call after-change hooks for the inserted text, aside from the case
3839 of normal visiting (not with REPLACE), which is done in a new buffer 3840 of normal visiting (not with REPLACE), which is done in a new buffer
3840 "before" the buffer is changed. */ 3841 "before" the buffer is changed. */
3841 if (inserted > 0 && total > 0 3842 if (inserted_chars > 0 && total > 0
3842 && (NILP (visit) || !NILP (replace))) 3843 && (NILP (visit) || !NILP (replace)))
3843 signal_after_change (PT, 0, inserted); 3844 signal_after_change (PT, 0, inserted_chars);
3844 3845
3845 Vlast_coding_system_used = coding.symbol; 3846 if (set_coding_system)
3847 Vlast_coding_system_used = coding.symbol;
3846 3848
3847 if (inserted > 0) 3849 if (inserted > 0)
3848 { 3850 {
@@ -3852,17 +3854,18 @@ This does code conversion according to the value of\n\
3852 3854
3853 while (!NILP (p)) 3855 while (!NILP (p))
3854 { 3856 {
3855 insval = call1 (Fcar (p), make_number (inserted)); 3857 insval = call1 (Fcar (p), make_number (inserted_chars));
3856 if (!NILP (insval)) 3858 if (!NILP (insval))
3857 { 3859 {
3858 CHECK_NUMBER (insval, 0); 3860 CHECK_NUMBER (insval, 0);
3859 inserted = XFASTINT (insval); 3861 inserted_chars = XFASTINT (insval);
3860 } 3862 }
3861 QUIT; 3863 QUIT;
3862 p = Fcdr (p); 3864 p = Fcdr (p);
3863 } 3865 }
3864 } 3866 }
3865 3867
3868 /* ??? Retval needs to be dealt with in all cases consistently. */
3866 if (NILP (val)) 3869 if (NILP (val))
3867 val = Fcons (orig_filename, 3870 val = Fcons (orig_filename,
3868 Fcons (make_number (inserted), 3871 Fcons (make_number (inserted),
@@ -3871,8 +3874,8 @@ This does code conversion according to the value of\n\
3871 RETURN_UNGCPRO (unbind_to (count, val)); 3874 RETURN_UNGCPRO (unbind_to (count, val));
3872} 3875}
3873 3876
3874static Lisp_Object build_annotations (); 3877static Lisp_Object build_annotations P_ ((Lisp_Object, Lisp_Object,
3875extern Lisp_Object Ffile_locked_p (); 3878 Lisp_Object));
3876 3879
3877/* If build_annotations switched buffers, switch back to BUF. 3880/* If build_annotations switched buffers, switch back to BUF.
3878 Kill the temporary buffer that was selected in the meantime. 3881 Kill the temporary buffer that was selected in the meantime.
@@ -4191,7 +4194,12 @@ to the file, instead of any buffer contents, and END is ignored.")
4191 && coding.type == coding_type_iso2022 4194 && coding.type == coding_type_iso2022
4192 && coding.flags & CODING_FLAG_ISO_DESIGNATE_AT_BOL 4195 && coding.flags & CODING_FLAG_ISO_DESIGNATE_AT_BOL
4193 && GPT > BEG && GPT_ADDR[-1] != '\n') 4196 && GPT > BEG && GPT_ADDR[-1] != '\n')
4194 move_gap (find_next_newline (GPT, 1)); 4197 {
4198 int opoint = PT, opoint_byte = PT_BYTE;
4199 scan_newline (PT, PT_BYTE, ZV, ZV_BYTE, 1, 0);
4200 move_gap_both (PT, PT_BYTE);
4201 SET_PT_BOTH (opoint, opoint_byte);
4202 }
4195#endif 4203#endif
4196 4204
4197 failure = 0; 4205 failure = 0;
@@ -4205,25 +4213,23 @@ to the file, instead of any buffer contents, and END is ignored.")
4205 } 4213 }
4206 else if (XINT (start) != XINT (end)) 4214 else if (XINT (start) != XINT (end))
4207 { 4215 {
4208 int nwritten = 0; 4216 register int end1 = CHAR_TO_BYTE (XINT (end));
4217
4218 tem = CHAR_TO_BYTE (XINT (start));
4219
4209 if (XINT (start) < GPT) 4220 if (XINT (start) < GPT)
4210 { 4221 {
4211 register int end1 = XINT (end); 4222 failure = 0 > a_write (desc, BYTE_POS_ADDR (tem),
4212 tem = XINT (start); 4223 min (GPT_BYTE, end1) - tem, tem, &annotations,
4213 failure = 0 > a_write (desc, POS_ADDR (tem),
4214 min (GPT, end1) - tem, tem, &annotations,
4215 &coding); 4224 &coding);
4216 nwritten += min (GPT, end1) - tem;
4217 save_errno = errno; 4225 save_errno = errno;
4218 } 4226 }
4219 4227
4220 if (XINT (end) > GPT && !failure) 4228 if (XINT (end) > GPT && !failure)
4221 { 4229 {
4222 tem = XINT (start); 4230 tem = max (tem, GPT_BYTE);
4223 tem = max (tem, GPT); 4231 failure = 0 > a_write (desc, BYTE_POS_ADDR (tem), end1 - tem,
4224 failure = 0 > a_write (desc, POS_ADDR (tem), XINT (end) - tem,
4225 tem, &annotations, &coding); 4232 tem, &annotations, &coding);
4226 nwritten += XINT (end) - tem;
4227 save_errno = errno; 4233 save_errno = errno;
4228 } 4234 }
4229 } 4235 }
@@ -4329,7 +4335,7 @@ to the file, instead of any buffer contents, and END is ignored.")
4329 4335
4330 return Qnil; 4336 return Qnil;
4331} 4337}
4332 4338
4333Lisp_Object merge (); 4339Lisp_Object merge ();
4334 4340
4335DEFUN ("car-less-than-car", Fcar_less_than_car, Scar_less_than_car, 2, 2, 0, 4341DEFUN ("car-less-than-car", Fcar_less_than_car, Scar_less_than_car, 2, 2, 0,
@@ -4421,43 +4427,51 @@ build_annotations (start, end, pre_write_conversion)
4421 UNGCPRO; 4427 UNGCPRO;
4422 return annotations; 4428 return annotations;
4423} 4429}
4424 4430
4425/* Write to descriptor DESC the LEN characters starting at ADDR, 4431/* Write to descriptor DESC the NBYTES bytes starting at ADDR,
4426 assuming they start at position POS in the buffer. 4432 assuming they start at byte position BYTEPOS in the buffer.
4427 Intersperse with them the annotations from *ANNOT 4433 Intersperse with them the annotations from *ANNOT
4428 (those which fall within the range of positions POS to POS + LEN), 4434 which fall within the range of byte positions BYTEPOS to BYTEPOS + NBYTES,
4429 each at its appropriate position. 4435 each at its appropriate position.
4430 4436
4431 Modify *ANNOT by discarding elements as we output them. 4437 We modify *ANNOT by discarding elements as we use them up.
4438
4432 The return value is negative in case of system call failure. */ 4439 The return value is negative in case of system call failure. */
4433 4440
4434int 4441static int
4435a_write (desc, addr, len, pos, annot, coding) 4442a_write (desc, addr, nbytes, bytepos, annot, coding)
4436 int desc; 4443 int desc;
4437 register char *addr; 4444 register char *addr;
4438 register int len; 4445 register int nbytes;
4439 int pos; 4446 int bytepos;
4440 Lisp_Object *annot; 4447 Lisp_Object *annot;
4441 struct coding_system *coding; 4448 struct coding_system *coding;
4442{ 4449{
4443 Lisp_Object tem; 4450 Lisp_Object tem;
4444 int nextpos; 4451 int nextpos;
4445 int lastpos = pos + len; 4452 int lastpos = bytepos + nbytes;
4446 4453
4447 while (NILP (*annot) || CONSP (*annot)) 4454 while (NILP (*annot) || CONSP (*annot))
4448 { 4455 {
4449 tem = Fcar_safe (Fcar (*annot)); 4456 tem = Fcar_safe (Fcar (*annot));
4450 if (INTEGERP (tem) && XINT (tem) >= pos && XFASTINT (tem) <= lastpos) 4457 nextpos = 0;
4451 nextpos = XFASTINT (tem); 4458 if (INTEGERP (tem))
4452 else 4459 nextpos = CHAR_TO_BYTE (XFASTINT (tem));
4453 return e_write (desc, addr, lastpos - pos, coding); 4460
4454 if (nextpos > pos) 4461 /* If there are no more annotations in this range,
4462 output the rest of the range all at once. */
4463 if (! (nextpos >= bytepos && nextpos <= lastpos))
4464 return e_write (desc, addr, lastpos - bytepos, coding);
4465
4466 /* Output buffer text up to the next annotation's position. */
4467 if (nextpos > bytepos)
4455 { 4468 {
4456 if (0 > e_write (desc, addr, nextpos - pos, coding)) 4469 if (0 > e_write (desc, addr, nextpos - bytepos, coding))
4457 return -1; 4470 return -1;
4458 addr += nextpos - pos; 4471 addr += nextpos - bytepos;
4459 pos = nextpos; 4472 bytepos = nextpos;
4460 } 4473 }
4474 /* Output the annotation. */
4461 tem = Fcdr (Fcar (*annot)); 4475 tem = Fcdr (Fcar (*annot));
4462 if (STRINGP (tem)) 4476 if (STRINGP (tem))
4463 { 4477 {
@@ -4473,11 +4487,14 @@ a_write (desc, addr, len, pos, annot, coding)
4473#define WRITE_BUF_SIZE (16 * 1024) 4487#define WRITE_BUF_SIZE (16 * 1024)
4474#endif 4488#endif
4475 4489
4476int 4490/* Write NBYTES bytes starting at ADDR into descriptor DESC,
4477e_write (desc, addr, len, coding) 4491 encoding them with coding system CODING. */
4492
4493static int
4494e_write (desc, addr, nbytes, coding)
4478 int desc; 4495 int desc;
4479 register char *addr; 4496 register char *addr;
4480 register int len; 4497 register int nbytes;
4481 struct coding_system *coding; 4498 struct coding_system *coding;
4482{ 4499{
4483 char buf[WRITE_BUF_SIZE]; 4500 char buf[WRITE_BUF_SIZE];
@@ -4487,20 +4504,20 @@ e_write (desc, addr, len, coding)
4487 now it is handled within encode_coding. */ 4504 now it is handled within encode_coding. */
4488 while (1) 4505 while (1)
4489 { 4506 {
4490 produced = encode_coding (coding, addr, buf, len, WRITE_BUF_SIZE, 4507 produced = encode_coding (coding, addr, buf, nbytes, WRITE_BUF_SIZE,
4491 &consumed); 4508 &consumed);
4492 len -= consumed, addr += consumed; 4509 nbytes -= consumed, addr += consumed;
4493 if (produced > 0) 4510 if (produced > 0)
4494 { 4511 {
4495 produced -= write (desc, buf, produced); 4512 produced -= write (desc, buf, produced);
4496 if (produced) return -1; 4513 if (produced) return -1;
4497 } 4514 }
4498 if (len <= 0) 4515 if (nbytes <= 0)
4499 break; 4516 break;
4500 } 4517 }
4501 return 0; 4518 return 0;
4502} 4519}
4503 4520
4504DEFUN ("verify-visited-file-modtime", Fverify_visited_file_modtime, 4521DEFUN ("verify-visited-file-modtime", Fverify_visited_file_modtime,
4505 Sverify_visited_file_modtime, 1, 1, 0, 4522 Sverify_visited_file_modtime, 1, 1, 0,
4506 "Return t if last mod time of BUF's visited file matches what BUF records.\n\ 4523 "Return t if last mod time of BUF's visited file matches what BUF records.\n\