aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorRichard M. Stallman1994-02-17 08:38:34 +0000
committerRichard M. Stallman1994-02-17 08:38:34 +0000
commit3d0387c0f3be8e915aef9c5733be5bcec5f8924c (patch)
tree30ddff283197c636a14f929990d9d9a86c2c10ec /src
parentf9456b0a5b508c8b031f9cc996e904d01bcdf697 (diff)
downloademacs-3d0387c0f3be8e915aef9c5733be5bcec5f8924c.tar.gz
emacs-3d0387c0f3be8e915aef9c5733be5bcec5f8924c.zip
(Finsert_file_contents): New arg REPLACE.
New feature to replace buffer contents with file contents.
Diffstat (limited to 'src')
-rw-r--r--src/fileio.c102
1 files changed, 97 insertions, 5 deletions
diff --git a/src/fileio.c b/src/fileio.c
index ee623182acd..ab2e6396cdb 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -2485,7 +2485,7 @@ Lisp_Object Qfind_buffer_file_type;
2485#endif 2485#endif
2486 2486
2487DEFUN ("insert-file-contents", Finsert_file_contents, Sinsert_file_contents, 2487DEFUN ("insert-file-contents", Finsert_file_contents, Sinsert_file_contents,
2488 1, 4, 0, 2488 1, 5, 0,
2489 "Insert contents of file FILENAME after point.\n\ 2489 "Insert contents of file FILENAME after point.\n\
2490Returns list of absolute file name and length of data inserted.\n\ 2490Returns list of absolute file name and length of data inserted.\n\
2491If second argument VISIT is non-nil, the buffer's visited filename\n\ 2491If second argument VISIT is non-nil, the buffer's visited filename\n\
@@ -2494,9 +2494,14 @@ If visiting and the file does not exist, visiting is completed\n\
2494before the error is signaled.\n\n\ 2494before the error is signaled.\n\n\
2495The optional third and fourth arguments BEG and END\n\ 2495The optional third and fourth arguments BEG and END\n\
2496specify what portion of the file to insert.\n\ 2496specify what portion of the file to insert.\n\
2497If VISIT is non-nil, BEG and END must be nil.") 2497If VISIT is non-nil, BEG and END must be nil.\n\
2498 (filename, visit, beg, end) 2498If optional fifth argument REPLACE is non-nil,\n\
2499 Lisp_Object filename, visit, beg, end; 2499it means replace the current buffer contents (in the accessible portion)\n\
2500with the file contents. This is better than simply deleting and inserting\n\
2501the whole thing because (1) it preserves some marker positions\n\
2502and (2) it puts less data in the undo list.")
2503 (filename, visit, beg, end, replace)
2504 Lisp_Object filename, visit, beg, end, replace;
2500{ 2505{
2501 struct stat st; 2506 struct stat st;
2502 register int fd; 2507 register int fd;
@@ -2523,7 +2528,8 @@ If VISIT is non-nil, BEG and END must be nil.")
2523 handler = Ffind_file_name_handler (filename); 2528 handler = Ffind_file_name_handler (filename);
2524 if (!NILP (handler)) 2529 if (!NILP (handler))
2525 { 2530 {
2526 val = call5 (handler, Qinsert_file_contents, filename, visit, beg, end); 2531 val = call6 (handler, Qinsert_file_contents, filename,
2532 visit, beg, end, replace);
2527 goto handled; 2533 goto handled;
2528 } 2534 }
2529 2535
@@ -2579,6 +2585,92 @@ If VISIT is non-nil, BEG and END must be nil.")
2579 error ("maximum buffer size exceeded"); 2585 error ("maximum buffer size exceeded");
2580 } 2586 }
2581 2587
2588 /* If requested, replace the accessible part of the buffer
2589 with the file contents. Avoid replacing text at the
2590 beginning or end of the buffer that matches the file contents;
2591 that preserves markers pointing to the unchanged parts. */
2592 if (!NILP (replace))
2593 {
2594 char buffer[1 << 14];
2595 int same_at_start = BEGV;
2596 int same_at_end = ZV;
2597 immediate_quit = 1;
2598 QUIT;
2599 /* Count how many chars at the start of the file
2600 match the text at the beginning of the buffer. */
2601 while (1)
2602 {
2603 int nread, bufpos;
2604
2605 nread = read (fd, buffer, sizeof buffer);
2606 if (nread < 0)
2607 error ("IO error reading %s: %s",
2608 XSTRING (filename)->data, strerror (errno));
2609 else if (nread == 0)
2610 break;
2611 bufpos = 0;
2612 while (bufpos < nread && same_at_start < ZV
2613 && FETCH_CHAR (same_at_start) == buffer[bufpos])
2614 same_at_start++, bufpos++;
2615 /* If we found a discrepancy, stop the scan.
2616 Otherwise loop around and scan the next bufferfull. */
2617 if (bufpos != nread)
2618 break;
2619 }
2620 immediate_quit = 0;
2621 /* If the file matches the buffer completely,
2622 there's no need to replace anything. */
2623 if (same_at_start == ZV)
2624 {
2625 close (fd);
2626 goto handled;
2627 }
2628 immediate_quit = 1;
2629 QUIT;
2630 /* Count how many chars at the end of the file
2631 match the text at the end of the buffer. */
2632 while (1)
2633 {
2634 int total_read, nread, bufpos, curpos, trial;
2635
2636 /* At what file position are we now scanning? */
2637 curpos = st.st_size - (ZV - same_at_end);
2638 /* How much can we scan in the next step? */
2639 trial = min (curpos, sizeof buffer);
2640 if (lseek (fd, curpos - trial, 0) < 0)
2641 report_file_error ("Setting file position",
2642 Fcons (filename, Qnil));
2643
2644 total_read = 0;
2645 while (total_read < trial)
2646 {
2647 nread = read (fd, buffer + total_read, trial - total_read);
2648 if (nread <= 0)
2649 error ("IO error reading %s: %s",
2650 XSTRING (filename)->data, strerror (errno));
2651 total_read += nread;
2652 }
2653 /* Scan this bufferfull from the end, comparing with
2654 the Emacs buffer. */
2655 bufpos = total_read;
2656 /* Compare with same_at_start to avoid counting some buffer text
2657 as matching both at the file's beginning and at the end. */
2658 while (bufpos > 0 && same_at_end > same_at_start
2659 && FETCH_CHAR (same_at_end - 1) == buffer[bufpos - 1])
2660 same_at_end--, bufpos--;
2661 /* If we found a discrepancy, stop the scan.
2662 Otherwise loop around and scan the preceding bufferfull. */
2663 if (bufpos != 0)
2664 break;
2665 }
2666 immediate_quit = 0;
2667 /* Arrange to read only the nonmatching middle part of the file. */
2668 XFASTINT (beg) = same_at_start - BEGV;
2669 XFASTINT (end) = st.st_size - (ZV - same_at_end);
2670 /* Delete the nonmatching middle part of the buffer. */
2671 Fdelete_region (make_number (same_at_start), make_number (same_at_end));
2672 }
2673
2582 total = XINT (end) - XINT (beg); 2674 total = XINT (end) - XINT (beg);
2583 2675
2584 { 2676 {