comparison src/fileio.c @ 20533:60b9e88f8743

(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.
author Richard M. Stallman <rms@gnu.org>
date Wed, 31 Dec 1997 22:16:35 +0000
parents 987ddd5cb6ee
children c9095cd30412
comparison
equal deleted inserted replaced
20532:7ffd3d9afeb4 20533:60b9e88f8743
228 228
229 Lisp_Object Qfile_name_history; 229 Lisp_Object Qfile_name_history;
230 230
231 Lisp_Object Qcar_less_than_car; 231 Lisp_Object Qcar_less_than_car;
232 232
233 static int a_write P_ ((int, char *, int, int,
234 Lisp_Object, struct coding_system *));
235 static int e_write P_ ((int, char *, int, struct coding_system *));
236
233 void 237 void
234 report_file_error (string, data) 238 report_file_error (string, data)
235 char *string; 239 char *string;
236 Lisp_Object data; 240 Lisp_Object data;
237 { 241 {
257 return Qnil; 261 return Qnil;
258 } 262 }
259 263
260 /* Restore point, having saved it as a marker. */ 264 /* Restore point, having saved it as a marker. */
261 265
262 Lisp_Object 266 static Lisp_Object
263 restore_point_unwind (location) 267 restore_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 }
270 274
271 Lisp_Object Qexpand_file_name; 275 Lisp_Object Qexpand_file_name;
447 DEFUN ("unhandled-file-name-directory", Funhandled_file_name_directory, Sunhandled_file_name_directory, 1, 1, 0, 451 DEFUN ("unhandled-file-name-directory", Funhandled_file_name_directory, Sunhandled_file_name_directory, 1, 1, 0,
448 "Return a directly usable directory name somehow associated with FILENAME.\n\ 452 "Return a directly usable directory name somehow associated with FILENAME.\n\
449 A `directly usable' directory name is one that may be used without the\n\ 453 A `directly usable' directory name is one that may be used without the\n\
450 intervention of any file handler.\n\ 454 intervention of any file handler.\n\
451 If FILENAME is a directly usable file itself, return\n\ 455 If FILENAME is a directly usable file itself, return\n\
452 (file-name-directory FILENAME).\n\ 456 \(file-name-directory FILENAME).\n\
453 The `call-process' and `start-process' functions use this function to\n\ 457 The `call-process' and `start-process' functions use this function to\n\
454 get a current directory to run processes in.") 458 get a current directory to run processes in.")
455 (filename) 459 (filename)
456 Lisp_Object filename; 460 Lisp_Object filename;
457 { 461 {
3074 #endif 3078 #endif
3075 3079
3076 DEFUN ("insert-file-contents", Finsert_file_contents, Sinsert_file_contents, 3080 DEFUN ("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\
3079 Returns list of absolute file name and length of data inserted.\n\ 3083 Returns list of absolute file name and number of bytes inserted.\n\
3080 If second argument VISIT is non-nil, the buffer's visited filename\n\ 3084 If second argument VISIT is non-nil, the buffer's visited filename\n\
3081 and last save file modtime are set, and it is marked unmodified.\n\ 3085 and last save file modtime are set, and it is marked unmodified.\n\
3082 If visiting and the file does not exist, visiting is completed\n\ 3086 If visiting and the file does not exist, visiting is completed\n\
3083 before the error is signaled.\n\ 3087 before the error is signaled.\n\
3084 The optional third and fourth arguments BEG and END\n\ 3088 The optional third and fourth arguments BEG and END\n\
3085 specify what portion of the file to insert.\n\ 3089 specify what portion of the file to insert.\n\
3090 These arguments count bytes in the file, not characters in the buffer.\n\
3086 If VISIT is non-nil, BEG and END must be nil.\n\ 3091 If VISIT is non-nil, BEG and END must be nil.\n\
3087 \n\ 3092 \n\
3088 If optional fifth argument REPLACE is non-nil,\n\ 3093 If optional fifth argument REPLACE is non-nil,\n\
3089 it means replace the current buffer contents (in the accessible portion)\n\ 3094 it means replace the current buffer contents (in the accessible portion)\n\
3090 with the file contents. This is better than simply deleting and inserting\n\ 3095 with the file contents. This is better than simply deleting and inserting\n\
3099 (filename, visit, beg, end, replace) 3104 (filename, visit, beg, end, replace)
3100 Lisp_Object filename, visit, beg, end, replace; 3105 Lisp_Object filename, visit, beg, end, replace;
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;
3108 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; 3114 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
3109 Lisp_Object handler, val, insval, orig_filename; 3115 Lisp_Object handler, val, insval, orig_filename;
3112 int not_regular = 0; 3118 int not_regular = 0;
3113 char read_buf[READ_BUF_SIZE]; 3119 char read_buf[READ_BUF_SIZE];
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");
3120 3127
3121 if (!NILP (current_buffer->read_only)) 3128 if (!NILP (current_buffer->read_only))
3289 But if we discover the need for conversion, we give up on this method 3296 But if we discover the need for conversion, we give up on this method
3290 and let the following if-statement handle the replace job. */ 3297 and let the following if-statement handle the replace job. */
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
3299 give up on handling REPLACE in the optimized way. */ 3309 give up on handling REPLACE in the optimized way. */
3300 int giveup_match_end = 0; 3310 int giveup_match_end = 0;
3341 giveup_match_end = 1; 3351 giveup_match_end = 1;
3342 break; 3352 break;
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.
3350 Otherwise loop around and scan the next bufferful. */ 3360 Otherwise loop around and scan the next bufferful. */
3351 if (bufpos != nread) 3361 if (bufpos != nread)
3352 break; 3362 break;
3353 } 3363 }
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--;
3361 /* Truncate the buffer to the size of the file. */ 3371 /* Truncate the buffer to the size of the file. */
3362 del_range_1 (same_at_start, same_at_end, 0); 3372 del_range_1 (same_at_start, same_at_end, 0);
3370 while (!giveup_match_end) 3380 while (!giveup_match_end)
3371 { 3381 {
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;
3379 /* How much can we scan in the next step? */ 3389 /* How much can we scan in the next step? */
3380 trial = min (curpos, sizeof buffer); 3390 trial = min (curpos, sizeof buffer);
3417 } 3427 }
3418 immediate_quit = 0; 3428 immediate_quit = 0;
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. */
3445 if (XBUFFER (XWINDOW (selected_window)->buffer) == current_buffer) 3460 if (XBUFFER (XWINDOW (selected_window)->buffer) == current_buffer)
3446 XWINDOW (selected_window)->start_at_line_beg = Fbolp (); 3461 XWINDOW (selected_window)->start_at_line_beg = Fbolp ();
3458 is needed, in a simple way that needs a lot of memory. 3473 is needed, in a simple way that needs a lot of memory.
3459 The preceding if-statement handles the case of no conversion 3474 The preceding if-statement handles the case of no conversion
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. */
3473 3489
3474 if (lseek (fd, XINT (beg), 0) < 0) 3490 if (lseek (fd, XINT (beg), 0) < 0)
3583 while (bufpos > 0 && same_at_end > same_at_start 3599 while (bufpos > 0 && same_at_end > same_at_start
3584 && FETCH_BYTE (same_at_end - 1) == conversion_buffer[bufpos - 1]) 3600 && FETCH_BYTE (same_at_end - 1) == conversion_buffer[bufpos - 1])
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
3592 /* If display currently starts at beginning of line, 3608 /* If display currently starts at beginning of line,
3593 keep it that way. */ 3609 keep it that way. */
3595 XWINDOW (selected_window)->start_at_line_beg = Fbolp (); 3611 XWINDOW (selected_window)->start_at_line_beg = Fbolp ();
3596 3612
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);
3608 specpdl_ptr--; 3625 specpdl_ptr--;
3609 3626
3651 { 3668 {
3652 /* try is reserved in some compilers (Microsoft C) */ 3669 /* try is reserved in some compilers (Microsoft C) */
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;
3662 QUIT; 3679 QUIT;
3663 this = read (fd, destination, trytry); 3680 this = read (fd, destination, trytry);
3675 so don't bother counting in HOW_MUCH. 3692 so don't bother counting in HOW_MUCH.
3676 (INSERTED is where we count the number of characters inserted.) */ 3693 (INSERTED is where we count the number of characters inserted.) */
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 {
3683 int require, produced, consumed; 3701 int require, produced, consumed;
3684 3702
3701 if (this == 0) 3719 if (this == 0)
3702 coding.last_block = 1; 3720 coding.last_block = 1;
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;
3717 } 3735 }
3718 } 3736 }
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;
3722 } 3740 this_chars = chars_in_text (BYTE_POS_ADDR (PT_BYTE + inserted - 1) + 1,
3723 3741 produced);
3724 GPT += this; 3742 }
3743
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;
3732 } 3756 inserted_chars += this_chars;
3733 3757 }
3734 3758
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
3738 conversion). */ 3762 conversion). */
3741 current_buffer->buffer_file_type = Qnil; 3765 current_buffer->buffer_file_type = Qnil;
3742 else 3766 else
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
3780 close (fd); 3779 close (fd);
3781 3780
3786 error ("IO error reading %s: %s", 3785 error ("IO error reading %s: %s",
3787 XSTRING (orig_filename)->data, strerror (errno)); 3786 XSTRING (orig_filename)->data, strerror (errno));
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
3794 if (!NILP (visit)) 3795 if (!NILP (visit))
3795 { 3796 {
3825 if (current_buffer->modtime == -1) 3826 if (current_buffer->modtime == -1)
3826 report_file_error ("Opening input file", Fcons (orig_filename, Qnil)); 3827 report_file_error ("Opening input file", Fcons (orig_filename, Qnil));
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 {
3849 p = Vafter_insert_file_functions; 3851 p = Vafter_insert_file_functions;
3850 if (!NILP (coding.post_read_conversion)) 3852 if (!NILP (coding.post_read_conversion))
3851 p = Fcons (coding.post_read_conversion, p); 3853 p = Fcons (coding.post_read_conversion, p);
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),
3869 Qnil)); 3872 Qnil));
3870 3873
3871 RETURN_UNGCPRO (unbind_to (count, val)); 3874 RETURN_UNGCPRO (unbind_to (count, val));
3872 } 3875 }
3873 3876
3874 static Lisp_Object build_annotations (); 3877 static Lisp_Object build_annotations P_ ((Lisp_Object, Lisp_Object,
3875 extern 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.
3879 3882
3880 Since this kill only the last temporary buffer, some buffers remain 3883 Since this kill only the last temporary buffer, some buffers remain
4189 when we must put designation sequences at beginning of line. */ 4192 when we must put designation sequences at beginning of line. */
4190 if (INTEGERP (start) 4193 if (INTEGERP (start)
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;
4198 immediate_quit = 1; 4206 immediate_quit = 1;
4199 4207
4203 XSTRING (start)->size, 0, &annotations, &coding); 4211 XSTRING (start)->size, 0, &annotations, &coding);
4204 save_errno = errno; 4212 save_errno = errno;
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 }
4230 else 4236 else
4231 { 4237 {
4327 if (!auto_saving) 4333 if (!auto_saving)
4328 message ("Wrote %s", XSTRING (visit_file)->data); 4334 message ("Wrote %s", XSTRING (visit_file)->data);
4329 4335
4330 return Qnil; 4336 return Qnil;
4331 } 4337 }
4332 4338
4333 Lisp_Object merge (); 4339 Lisp_Object merge ();
4334 4340
4335 DEFUN ("car-less-than-car", Fcar_less_than_car, Scar_less_than_car, 2, 2, 0, 4341 DEFUN ("car-less-than-car", Fcar_less_than_car, Scar_less_than_car, 2, 2, 0,
4336 "Return t if (car A) is numerically less than (car B).") 4342 "Return t if (car A) is numerically less than (car B).")
4337 (a, b) 4343 (a, b)
4419 } 4425 }
4420 4426
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
4434 int 4441 static int
4435 a_write (desc, addr, len, pos, annot, coding) 4442 a_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,
4455 { 4462 output the rest of the range all at once. */
4456 if (0 > e_write (desc, addr, nextpos - pos, coding)) 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)
4468 {
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 {
4464 if (0 > e_write (desc, XSTRING (tem)->data, XSTRING (tem)->size, 4478 if (0 > e_write (desc, XSTRING (tem)->data, XSTRING (tem)->size,
4465 coding)) 4479 coding))
4471 4485
4472 #ifndef WRITE_BUF_SIZE 4486 #ifndef WRITE_BUF_SIZE
4473 #define WRITE_BUF_SIZE (16 * 1024) 4487 #define WRITE_BUF_SIZE (16 * 1024)
4474 #endif 4488 #endif
4475 4489
4476 int 4490 /* Write NBYTES bytes starting at ADDR into descriptor DESC,
4477 e_write (desc, addr, len, coding) 4491 encoding them with coding system CODING. */
4492
4493 static int
4494 e_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];
4484 int produced, consumed; 4501 int produced, consumed;
4485 4502
4486 /* We used to have a code for handling selective display here. But, 4503 /* We used to have a code for handling selective display here. But,
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
4504 DEFUN ("verify-visited-file-modtime", Fverify_visited_file_modtime, 4521 DEFUN ("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\
4507 This means that the file has not been changed since it was visited or saved.") 4524 This means that the file has not been changed since it was visited or saved.")
4508 (buf) 4525 (buf)