aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorRichard M. Stallman1993-10-09 21:30:48 +0000
committerRichard M. Stallman1993-10-09 21:30:48 +0000
commitd6a3cc1563d5c25456f430a3087b4fa6fd3505dd (patch)
tree8e8a40607def489b88b542e23b6934cb24ae888a /src
parent149df30fea0649d3909979b7215e9c20f93d6ac6 (diff)
downloademacs-d6a3cc1563d5c25456f430a3087b4fa6fd3505dd.tar.gz
emacs-d6a3cc1563d5c25456f430a3087b4fa6fd3505dd.zip
(Vafter_insert_file_functions): New variable.
(Vwrite_region_annotate_functions): New variable. (Qcar_less_than_car): New variable. (Fcar_less_than_car): New function. (syms_of_fileio): Make Lisp variables and function available. staticpro Qcar_less_than_car. (a_write, build_annotations): New functions. (Fwrite_region): Call them. (Finsert_file_contents): Run the Vafter_insert_file_functions.
Diffstat (limited to 'src')
-rw-r--r--src/fileio.c178
1 files changed, 164 insertions, 14 deletions
diff --git a/src/fileio.c b/src/fileio.c
index 347585fc4d2..c2fca1b375b 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -100,6 +100,12 @@ int auto_save_mode_bits;
100 whose I/O is done with a special handler. */ 100 whose I/O is done with a special handler. */
101Lisp_Object Vfile_name_handler_alist; 101Lisp_Object Vfile_name_handler_alist;
102 102
103/* Functions to be called to process text properties in inserted file. */
104Lisp_Object Vafter_insert_file_functions;
105
106/* Functions to be called to create text property annotations for file. */
107Lisp_Object Vwrite_region_annotate_functions;
108
103/* Nonzero means, when reading a filename in the minibuffer, 109/* Nonzero means, when reading a filename in the minibuffer,
104 start out by inserting the default directory into the minibuffer. */ 110 start out by inserting the default directory into the minibuffer. */
105int insert_default_directory; 111int insert_default_directory;
@@ -112,6 +118,8 @@ Lisp_Object Qfile_error, Qfile_already_exists;
112 118
113Lisp_Object Qfile_name_history; 119Lisp_Object Qfile_name_history;
114 120
121Lisp_Object Qcar_less_than_car;
122
115report_file_error (string, data) 123report_file_error (string, data)
116 char *string; 124 char *string;
117 Lisp_Object data; 125 Lisp_Object data;
@@ -2353,13 +2361,15 @@ If VISIT is non-nil, BEG and END must be nil.")
2353 register int inserted = 0; 2361 register int inserted = 0;
2354 register int how_much; 2362 register int how_much;
2355 int count = specpdl_ptr - specpdl; 2363 int count = specpdl_ptr - specpdl;
2356 struct gcpro gcpro1; 2364 struct gcpro gcpro1, gcpro2;
2357 Lisp_Object handler, val; 2365 Lisp_Object handler, val, insval;
2366 Lisp_Object p;
2358 int total; 2367 int total;
2359 2368
2360 val = Qnil; 2369 val = Qnil;
2370 p = Qnil;
2361 2371
2362 GCPRO1 (filename); 2372 GCPRO2 (filename, p);
2363 if (!NILP (current_buffer->read_only)) 2373 if (!NILP (current_buffer->read_only))
2364 Fbarf_if_buffer_read_only(); 2374 Fbarf_if_buffer_read_only();
2365 2375
@@ -2523,6 +2533,22 @@ If VISIT is non-nil, BEG and END must be nil.")
2523 2533
2524 signal_after_change (point, 0, inserted); 2534 signal_after_change (point, 0, inserted);
2525 2535
2536 if (inserted > 0)
2537 {
2538 p = Vafter_insert_file_functions;
2539 while (!NILP (p))
2540 {
2541 insval = call1 (Fcar (p), make_number (inserted));
2542 if (!NILP (insval))
2543 {
2544 CHECK_NUMBER (insval, 0);
2545 inserted = XFASTINT (insval);
2546 }
2547 QUIT;
2548 p = Fcdr (p);
2549 }
2550 }
2551
2526 if (!NILP (val)) 2552 if (!NILP (val))
2527 RETURN_UNGCPRO (val); 2553 RETURN_UNGCPRO (val);
2528 RETURN_UNGCPRO (Fcons (filename, 2554 RETURN_UNGCPRO (Fcons (filename,
@@ -2530,6 +2556,8 @@ If VISIT is non-nil, BEG and END must be nil.")
2530 Qnil))); 2556 Qnil)));
2531} 2557}
2532 2558
2559static Lisp_Object build_annotations ();
2560
2533DEFUN ("write-region", Fwrite_region, Swrite_region, 3, 5, 2561DEFUN ("write-region", Fwrite_region, Swrite_region, 3, 5,
2534 "r\nFWrite region to file: ", 2562 "r\nFWrite region to file: ",
2535 "Write current region into specified file.\n\ 2563 "Write current region into specified file.\n\
@@ -2555,13 +2583,15 @@ to the file, instead of any buffer contents, and END is ignored.")
2555 int save_errno; 2583 int save_errno;
2556 unsigned char *fn; 2584 unsigned char *fn;
2557 struct stat st; 2585 struct stat st;
2558 int tem; 2586 int tem, tem2;
2559 int count = specpdl_ptr - specpdl; 2587 int count = specpdl_ptr - specpdl;
2560#ifdef VMS 2588#ifdef VMS
2561 unsigned char *fname = 0; /* If non-0, original filename (must rename) */ 2589 unsigned char *fname = 0; /* If non-0, original filename (must rename) */
2562#endif /* VMS */ 2590#endif /* VMS */
2563 Lisp_Object handler; 2591 Lisp_Object handler;
2564 Lisp_Object visit_file; 2592 Lisp_Object visit_file;
2593 Lisp_Object annotations;
2594 int visiting, quietly;
2565 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; 2595 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
2566 2596
2567 /* Special kludge to simplify auto-saving */ 2597 /* Special kludge to simplify auto-saving */
@@ -2579,7 +2609,12 @@ to the file, instead of any buffer contents, and END is ignored.")
2579 else 2609 else
2580 visit_file = filename; 2610 visit_file = filename;
2581 2611
2582 GCPRO4 (start, filename, visit, visit_file); 2612 visiting = (EQ (visit, Qt) || XTYPE (visit) == Lisp_String);
2613 quietly = !NILP (visit);
2614
2615 annotations = Qnil;
2616
2617 GCPRO4 (start, filename, annotations, visit_file);
2583 2618
2584 /* If the file name has special constructs in it, 2619 /* If the file name has special constructs in it,
2585 call the corresponding file handler. */ 2620 call the corresponding file handler. */
@@ -2594,7 +2629,7 @@ to the file, instead of any buffer contents, and END is ignored.")
2594 /* Do this before reporting IO error 2629 /* Do this before reporting IO error
2595 to avoid a "file has changed on disk" warning on 2630 to avoid a "file has changed on disk" warning on
2596 next attempt to save. */ 2631 next attempt to save. */
2597 if (EQ (visit, Qt) || XTYPE (visit) == Lisp_String) 2632 if (visiting)
2598 { 2633 {
2599 current_buffer->modtime = 0; 2634 current_buffer->modtime = 0;
2600 current_buffer->save_modified = MODIFF; 2635 current_buffer->save_modified = MODIFF;
@@ -2605,6 +2640,8 @@ to the file, instead of any buffer contents, and END is ignored.")
2605 return val; 2640 return val;
2606 } 2641 }
2607 2642
2643 annotations = build_annotations (start, end);
2644
2608#ifdef CLASH_DETECTION 2645#ifdef CLASH_DETECTION
2609 if (!auto_saving) 2646 if (!auto_saving)
2610 lock_file (visit_file); 2647 lock_file (visit_file);
@@ -2713,18 +2750,20 @@ to the file, instead of any buffer contents, and END is ignored.")
2713 2750
2714 if (XTYPE (start) == Lisp_String) 2751 if (XTYPE (start) == Lisp_String)
2715 { 2752 {
2716 failure = 0 > e_write (desc, XSTRING (start)->data, 2753 failure = 0 > a_write (desc, XSTRING (start)->data,
2717 XSTRING (start)->size); 2754 XSTRING (start)->size, 0, &annotations);
2718 save_errno = errno; 2755 save_errno = errno;
2719 } 2756 }
2720 else if (XINT (start) != XINT (end)) 2757 else if (XINT (start) != XINT (end))
2721 { 2758 {
2759 tem2 = 1;
2722 if (XINT (start) < GPT) 2760 if (XINT (start) < GPT)
2723 { 2761 {
2724 register int end1 = XINT (end); 2762 register int end1 = XINT (end);
2725 tem = XINT (start); 2763 tem = XINT (start);
2726 failure = 0 > e_write (desc, &FETCH_CHAR (tem), 2764 failure = 0 > a_write (desc, &FETCH_CHAR (tem),
2727 min (GPT, end1) - tem); 2765 min (GPT, end1) - tem, 1, &annotations);
2766 tem2 += min (GPT, end1) - tem;
2728 save_errno = errno; 2767 save_errno = errno;
2729 } 2768 }
2730 2769
@@ -2732,7 +2771,15 @@ to the file, instead of any buffer contents, and END is ignored.")
2732 { 2771 {
2733 tem = XINT (start); 2772 tem = XINT (start);
2734 tem = max (tem, GPT); 2773 tem = max (tem, GPT);
2735 failure = 0 > e_write (desc, &FETCH_CHAR (tem), XINT (end) - tem); 2774 failure = 0 > a_write (desc, &FETCH_CHAR (tem), XINT (end) - tem,
2775 tem2, &annotations);
2776 tem2 += XINT (end) - tem;
2777 save_errno = errno;
2778 }
2779 if (tem2 == 1)
2780 {
2781 /* If file was empty, still need to write the annotations */
2782 failure = 0 > a_write (desc, "", 0, 1, &annotations);
2736 save_errno = errno; 2783 save_errno = errno;
2737 } 2784 }
2738 } 2785 }
@@ -2795,19 +2842,19 @@ to the file, instead of any buffer contents, and END is ignored.")
2795 /* Do this before reporting IO error 2842 /* Do this before reporting IO error
2796 to avoid a "file has changed on disk" warning on 2843 to avoid a "file has changed on disk" warning on
2797 next attempt to save. */ 2844 next attempt to save. */
2798 if (EQ (visit, Qt) || XTYPE (visit) == Lisp_String) 2845 if (visiting)
2799 current_buffer->modtime = st.st_mtime; 2846 current_buffer->modtime = st.st_mtime;
2800 2847
2801 if (failure) 2848 if (failure)
2802 error ("IO error writing %s: %s", fn, err_str (save_errno)); 2849 error ("IO error writing %s: %s", fn, err_str (save_errno));
2803 2850
2804 if (EQ (visit, Qt) || XTYPE (visit) == Lisp_String) 2851 if (visiting)
2805 { 2852 {
2806 current_buffer->save_modified = MODIFF; 2853 current_buffer->save_modified = MODIFF;
2807 XFASTINT (current_buffer->save_length) = Z - BEG; 2854 XFASTINT (current_buffer->save_length) = Z - BEG;
2808 current_buffer->filename = visit_file; 2855 current_buffer->filename = visit_file;
2809 } 2856 }
2810 else if (!NILP (visit)) 2857 else if (quietly)
2811 return Qnil; 2858 return Qnil;
2812 2859
2813 if (!auto_saving) 2860 if (!auto_saving)
@@ -2816,6 +2863,87 @@ to the file, instead of any buffer contents, and END is ignored.")
2816 return Qnil; 2863 return Qnil;
2817} 2864}
2818 2865
2866Lisp_Object merge ();
2867
2868DEFUN ("car-less-than-car", Fcar_less_than_car, Scar_less_than_car, 2, 2, 0,
2869 "Return t if (car A) is numerically less than (car B)."
2870 (a, b)
2871 Lisp_Object a, b;
2872{
2873 return Flss (Fcar (a), Fcar (b));
2874}
2875
2876/* Build the complete list of annotations appropriate for writing out
2877 the text between START and END, by calling all the functions in
2878 write-region-annotate-functions and merging the lists they return. */
2879
2880static Lisp_Object
2881build_annotations (start, end)
2882 Lisp_Object start, end;
2883{
2884 Lisp_Object annotations;
2885 Lisp_Object p, res;
2886 struct gcpro gcpro1, gcpro2;
2887
2888 annotations = Qnil;
2889 p = Vwrite_region_annotate_functions;
2890 GCPRO2 (annotations, p);
2891 while (!NILP (p))
2892 {
2893 res = call2 (Fcar (p), start, end);
2894 Flength (res); /* Check basic validity of return value */
2895 annotations = merge (annotations, res, Qcar_less_than_car);
2896 p = Fcdr (p);
2897 }
2898 UNGCPRO;
2899 return annotations;
2900}
2901
2902/* Write to descriptor DESC the LEN characters starting at ADDR,
2903 assuming they start at position POS in the buffer.
2904 Intersperse with them the annotations from *ANNOT
2905 (those which fall within the range of positions POS to POS + LEN),
2906 each at its appropriate position.
2907
2908 Modify *ANNOT by discarding elements as we output them.
2909 The return value is negative in case of system call failure. */
2910
2911int
2912a_write (desc, addr, len, pos, annot)
2913 int desc;
2914 register char *addr;
2915 register int len;
2916 int pos;
2917 Lisp_Object *annot;
2918{
2919 Lisp_Object tem;
2920 int nextpos;
2921 int lastpos = pos + len;
2922
2923 while (1)
2924 {
2925 tem = Fcar_safe (Fcar (*annot));
2926 if (INTEGERP (tem) && XINT (tem) >= pos && XFASTINT (tem) <= lastpos)
2927 nextpos = XFASTINT (tem);
2928 else
2929 return e_write (desc, addr, lastpos - pos);
2930 if (nextpos > pos)
2931 {
2932 if (0 > e_write (desc, addr, nextpos - pos))
2933 return -1;
2934 addr += nextpos - pos;
2935 pos = nextpos;
2936 }
2937 tem = Fcdr (Fcar (*annot));
2938 if (STRINGP (tem))
2939 {
2940 if (0 > e_write (desc, XSTRING (tem)->data, XSTRING (tem)->size))
2941 return -1;
2942 }
2943 *annot = Fcdr (*annot);
2944 }
2945}
2946
2819int 2947int
2820e_write (desc, addr, len) 2948e_write (desc, addr, len)
2821 int desc; 2949 int desc;
@@ -3411,6 +3539,9 @@ syms_of_fileio ()
3411 Qfile_already_exists = intern("file-already-exists"); 3539 Qfile_already_exists = intern("file-already-exists");
3412 staticpro (&Qfile_already_exists); 3540 staticpro (&Qfile_already_exists);
3413 3541
3542 Qcar_less_than_car = intern ("car-less-than-car");
3543 staticpro (&Qcar_less_than_car);
3544
3414 Fput (Qfile_error, Qerror_conditions, 3545 Fput (Qfile_error, Qerror_conditions,
3415 Fcons (Qfile_error, Fcons (Qerror, Qnil))); 3546 Fcons (Qfile_error, Fcons (Qerror, Qnil)));
3416 Fput (Qfile_error, Qerror_message, 3547 Fput (Qfile_error, Qerror_message,
@@ -3446,6 +3577,24 @@ The function `find-file-name-handler' checks this list for a handler\n\
3446for its argument."); 3577for its argument.");
3447 Vfile_name_handler_alist = Qnil; 3578 Vfile_name_handler_alist = Qnil;
3448 3579
3580 DEFVAR_LISP ("after-insert-file-functions", &Vafter_insert_file_functions,
3581 "A list of functions to be called at the end of `insert-file-contents'.
3582Each is passed one argument, the number of bytes inserted. It should return
3583the new byte count, and leave point the same. If `insert-file-contents' is
3584intercepted by a handler from `file-name-handler-alist', that handler is
3585responsible for calling the after-insert-file-functions if appropriate.");
3586 Vafter_insert_file_functions = Qnil;
3587
3588 DEFVAR_LISP ("write-region-annotate-functions", &Vwrite_region_annotate_functions,
3589 "A list of functions to be called at the start of `write-region'.
3590Each is passed two arguments, START and END as for `write-region'. It should
3591return a list of pairs (POSITION . STRING) of strings to be effectively
3592inserted at the specified positions of the file being written (1 means to
3593insert before the first byte written). The POSITIONs must be sorted into
3594increasing order. If there are several functions in the list, the several
3595lists are merged destructively.");
3596 Vwrite_region_annotate_functions = Qnil;
3597
3449 defsubr (&Sfind_file_name_handler); 3598 defsubr (&Sfind_file_name_handler);
3450 defsubr (&Sfile_name_directory); 3599 defsubr (&Sfile_name_directory);
3451 defsubr (&Sfile_name_nondirectory); 3600 defsubr (&Sfile_name_nondirectory);
@@ -3485,6 +3634,7 @@ for its argument.");
3485 defsubr (&Sfile_newer_than_file_p); 3634 defsubr (&Sfile_newer_than_file_p);
3486 defsubr (&Sinsert_file_contents); 3635 defsubr (&Sinsert_file_contents);
3487 defsubr (&Swrite_region); 3636 defsubr (&Swrite_region);
3637 defsubr (&Scar_less_than_car);
3488 defsubr (&Sverify_visited_file_modtime); 3638 defsubr (&Sverify_visited_file_modtime);
3489 defsubr (&Sclear_visited_file_modtime); 3639 defsubr (&Sclear_visited_file_modtime);
3490 defsubr (&Svisited_file_modtime); 3640 defsubr (&Svisited_file_modtime);