/* File IO for GNU Emacs.
Copyright (C) 1985, 1986, 1987, 1988, 1993, 1994, 1995, 1996,
1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
- 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+ 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
This file is part of GNU Emacs.
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
+#include <setjmp.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
/* Functions to be called to create text property annotations for file. */
Lisp_Object Vwrite_region_annotate_functions;
Lisp_Object Qwrite_region_annotate_functions;
+Lisp_Object Vwrite_region_post_annotation_function;
/* During build_annotations, each time an annotation function is called,
this holds the annotations made by the previous functions. */
Lisp_Object Vwrite_region_annotations_so_far;
+/* Each time an annotation function changes the buffer, the new buffer
+ is added here. */
+Lisp_Object Vwrite_region_annotation_buffers;
+
/* File name in which we write a list of all our auto save files. */
Lisp_Object Vauto_save_list_file_name;
/* Whether or not files are auto-saved into themselves. */
Lisp_Object Vauto_save_visited_file_name;
+/* Whether or not to continue auto-saving after a large deletion. */
+Lisp_Object Vauto_save_include_big_deletions;
+
/* On NT, specifies the directory separator character, used (eg.) when
expanding file names. This can be bound to / or \. */
Lisp_Object Vdirectory_sep_char;
#endif
/* Non-zero means call move-file-to-trash in Fdelete_file or
- Fdelete_directory. */
+ Fdelete_directory_internal. */
int delete_by_moving_to_trash;
Lisp_Object Qdelete_by_moving_to_trash;
extern int minibuffer_auto_raise;
-extern int history_delete_duplicates;
-
/* These variables describe handlers that have "already" had a chance
to handle the current operation.
int c;
str = (char *) SDATA (errstring);
- c = STRING_CHAR (str, 0);
+ c = STRING_CHAR (str);
Faset (errstring, make_number (0), make_number (DOWNCASE (c)));
}
Lisp_Object Qcopy_file;
Lisp_Object Qmake_directory_internal;
Lisp_Object Qmake_directory;
-Lisp_Object Qdelete_directory;
+Lisp_Object Qdelete_directory_internal;
Lisp_Object Qdelete_file;
Lisp_Object Qrename_file;
Lisp_Object Qadd_name_to_file;
return call2 (handler, Qfile_name_directory, filename);
filename = FILE_SYSTEM_CASE (filename);
- beg = SDATA (filename);
#ifdef DOS_NT
- beg = strcpy (alloca (strlen (beg) + 1), beg);
+ beg = (unsigned char *) alloca (SBYTES (filename) + 1);
+ bcopy (SDATA (filename), beg, SBYTES (filename) + 1);
+#else
+ beg = SDATA (filename);
#endif
p = beg + SBYTES (filename);
STRING_MULTIBYTE (directory));
}
-static char make_temp_name_tbl[64] =
+static const char make_temp_name_tbl[64] =
{
'A','B','C','D','E','F','G','H',
'I','J','K','L','M','N','O','P',
}
}
- nm = SDATA (name);
-
/* Make a local copy of nm[] to protect it from GC in DECODE_FILE below. */
- nm = strcpy (alloca (strlen (nm) + 1), nm);
+ nm = (unsigned char *) alloca (SBYTES (name) + 1);
+ bcopy (SDATA (name), nm, SBYTES (name) + 1);
#ifdef DOS_NT
/* Note if special escape prefix is present, but remove for now. */
#endif
&& (IS_DIRECTORY_SEP (p[3]) || p[3] == 0))
{
+#ifdef WINDOWSNT
+ unsigned char *prev_o = o;
+#endif
while (o != target && (--o) && !IS_DIRECTORY_SEP (*o))
;
+#ifdef WINDOWSNT
+ /* Don't go below server level in UNC filenames. */
+ if (o == target + 1 && IS_DIRECTORY_SEP (*o)
+ && IS_DIRECTORY_SEP (*target))
+ o = prev_o;
+ else
+#endif
/* Keep initial / only if this is the whole name. */
if (o == target && IS_ANY_SEP (*o) && p[3] == 0)
++o;
the value of that variable. The variable name should be terminated
with a character not a letter, digit or underscore; otherwise, enclose
the entire variable name in braces.
-If `/~' appears, all of FILENAME through that `/' is discarded. */)
+
+If `/~' appears, all of FILENAME through that `/' is discarded.
+If `//' appears, everything up to and including the first of
+those `/' is discarded. */)
(filename)
Lisp_Object filename;
{
unsigned char *target = NULL;
int total = 0;
int substituted = 0;
+ int multibyte;
unsigned char *xnm;
Lisp_Object handler;
CHECK_STRING (filename);
+ multibyte = STRING_MULTIBYTE (filename);
+
/* If the file name has special constructs in it,
call the corresponding file handler. */
handler = Ffind_file_name_handler (filename, Qsubstitute_in_file_name);
if (!NILP (handler))
return call2 (handler, Qsubstitute_in_file_name, filename);
- nm = SDATA (filename);
+ /* Always work on a copy of the string, in case GC happens during
+ decode of environment variables, causing the original Lisp_String
+ data to be relocated. */
+ nm = (unsigned char *) alloca (SBYTES (filename) + 1);
+ bcopy (SDATA (filename), nm, SBYTES (filename) + 1);
+
#ifdef DOS_NT
- nm = strcpy (alloca (strlen (nm) + 1), nm);
CORRECT_DIR_SEPS (nm);
substituted = (strcmp (nm, SDATA (filename)) != 0);
#endif
again. Important with filenames like "/home/foo//:/hello///there"
which whould substitute to "/:/hello///there" rather than "/there". */
return Fsubstitute_in_file_name
- (make_specified_string (p, -1, endp - p,
- STRING_MULTIBYTE (filename)));
-
+ (make_specified_string (p, -1, endp - p, multibyte));
/* See if any variables are substituted into the string
and find the total length of their values in `total' */
/* Get variable value */
o = (unsigned char *) egetenv (target);
if (o)
- { /* Eight-bit chars occupy upto 2 bytes in multibyte. */
- total += strlen (o) * (STRING_MULTIBYTE (filename) ? 2 : 1);
+ {
+ /* Don't try to guess a maximum length - UTF8 can use up to
+ four bytes per character. This code is unlikely to run
+ in a situation that requires performance, so decoding the
+ env variables twice should be acceptable. Note that
+ decoding may cause a garbage collect. */
+ Lisp_Object orig, decoded;
+ orig = make_unibyte_string (o, strlen (o));
+ decoded = DECODE_FILE (orig);
+ total += SBYTES (decoded);
substituted = 1;
}
else if (*p == '}')
*x++ = '$';
strcpy (x, target); x+= strlen (target);
}
- else if (STRING_MULTIBYTE (filename))
- {
- /* If the original string is multibyte,
- convert what we substitute into multibyte. */
- while (*o)
- {
- int c = *o++;
- c = unibyte_char_to_multibyte (c);
- x += CHAR_STRING (c, x);
- }
- }
else
{
- strcpy (x, o);
- x += strlen (o);
+ Lisp_Object orig, decoded;
+ int orig_length, decoded_length;
+ orig_length = strlen (o);
+ orig = make_unibyte_string (o, orig_length);
+ decoded = DECODE_FILE (orig);
+ decoded_length = SBYTES (decoded);
+ strncpy (x, SDATA (decoded), decoded_length);
+ x += decoded_length;
+
+ /* If environment variable needed decoding, return value
+ needs to be multibyte. */
+ if (decoded_length != orig_length
+ || strncmp (SDATA (decoded), o, orig_length))
+ multibyte = 1;
}
}
need to quote some $ to $$ first. */
xnm = p;
- return make_specified_string (xnm, -1, x - xnm, STRING_MULTIBYTE (filename));
+ return make_specified_string (xnm, -1, x - xnm, multibyte);
badsubst:
error ("Bad format environment-variable substitution");
return Qnil;
}
-DEFUN ("delete-directory", Fdelete_directory, Sdelete_directory, 1, 1, "FDelete directory: ",
+DEFUN ("delete-directory-internal", Fdelete_directory_internal,
+ Sdelete_directory_internal, 1, 1, 0,
doc: /* Delete the directory named DIRECTORY. Does not follow symlinks. */)
(directory)
Lisp_Object directory;
CHECK_STRING (directory);
directory = Fdirectory_file_name (Fexpand_file_name (directory, Qnil));
- handler = Ffind_file_name_handler (directory, Qdelete_directory);
- if (!NILP (handler))
- return call2 (handler, Qdelete_directory, directory);
-
if (delete_by_moving_to_trash)
return call1 (Qmove_file_to_trash, directory);
#define READ_BUF_SIZE (64 << 10)
#endif
-extern void adjust_markers_for_delete P_ ((int, int, int, int));
-
/* This function is called after Lisp functions to decide a coding
system are called, or when they cause an error. Before they are
called, the current buffer is set unibyte and it contains only a
/* Used to pass values from insert-file-contents to read_non_regular. */
static int non_regular_fd;
-static int non_regular_inserted;
-static int non_regular_nbytes;
+static EMACS_INT non_regular_inserted;
+static EMACS_INT non_regular_nbytes;
/* Read from a non-regular file.
static Lisp_Object
read_non_regular ()
{
- int nbytes;
+ EMACS_INT nbytes;
immediate_quit = 1;
QUIT;
{
struct stat st;
register int fd;
- int inserted = 0;
+ EMACS_INT inserted = 0;
int nochange = 0;
- register int how_much;
- register int unprocessed;
+ register EMACS_INT how_much;
+ register EMACS_INT unprocessed;
int count = SPECPDL_INDEX ();
struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
Lisp_Object handler, val, insval, orig_filename, old_undo;
Lisp_Object p;
- int total = 0;
+ EMACS_INT total = 0;
int not_regular = 0;
unsigned char read_buf[READ_BUF_SIZE];
struct coding_system coding;
overflow. The calculations below double the file size
twice, so check that it can be multiplied by 4 safely. */
if (XINT (end) != st.st_size
- || st.st_size > INT_MAX / 4)
+ /* Actually, it should test either INT_MAX or LONG_MAX
+ depending on which one is used for EMACS_INT. But in
+ any case, in practice, this test is redundant with the
+ one above.
+ || st.st_size > INT_MAX / 4 */)
error ("Maximum buffer size exceeded");
/* The file size returned from stat may be zero, but data
We assume that the 1K-byte and 3K-byte for heading
and tailing respectively are sufficient for this
purpose. */
- int nread;
+ EMACS_INT nread;
if (st.st_size <= (1024 * 4))
nread = emacs_read (fd, read_buf, 1024 * 4);
/* same_at_start and same_at_end count bytes,
because file access counts bytes
and BEG and END count bytes. */
- int same_at_start = BEGV_BYTE;
- int same_at_end = ZV_BYTE;
- int overlap;
+ EMACS_INT same_at_start = BEGV_BYTE;
+ EMACS_INT same_at_end = ZV_BYTE;
+ EMACS_INT overlap;
/* There is still a possibility we will find the need to do code
conversion. If that happens, we set this variable to 1 to
give up on handling REPLACE in the optimized way. */
match the text at the beginning of the buffer. */
while (1)
{
- int nread, bufpos;
+ EMACS_INT nread, bufpos;
nread = emacs_read (fd, buffer, sizeof buffer);
if (nread < 0)
already found that decoding is necessary, don't waste time. */
while (!giveup_match_end)
{
- int total_read, nread, bufpos, curpos, trial;
+ EMACS_INT total_read, nread, bufpos, curpos, trial;
/* At what file position are we now scanning? */
curpos = XINT (end) - (ZV_BYTE - same_at_end);
if (! giveup_match_end)
{
- int temp;
+ EMACS_INT temp;
/* We win! We can handle REPLACE the optimized way. */
EMACS_INT overlap;
EMACS_INT bufpos;
unsigned char *decoded;
- int temp;
+ EMACS_INT temp;
int this_count = SPECPDL_INDEX ();
int multibyte = ! NILP (current_buffer->enable_multibyte_characters);
Lisp_Object conversion_buffer;
/* We read one bunch by one (READ_BUF_SIZE bytes) to allow
quitting while reading a huge while. */
/* try is reserved in some compilers (Microsoft C) */
- int trytry = min (total - how_much, READ_BUF_SIZE - unprocessed);
- int this;
+ EMACS_INT trytry = min (total - how_much,
+ READ_BUF_SIZE - unprocessed);
+ EMACS_INT this;
/* Allow quitting out of the actual I/O. */
immediate_quit = 1;
coding.mode &= ~CODING_MODE_LAST_BLOCK;
}
+ coding_system = CODING_ID_NAME (coding.id);
+ set_coding_system = 1;
decoded = BUF_BEG_ADDR (XBUFFER (conversion_buffer));
inserted = (BUF_Z_BYTE (XBUFFER (conversion_buffer))
- BUF_BEG_BYTE (XBUFFER (conversion_buffer)));
/* Here, we don't do code conversion in the loop. It is done by
decode_coding_gap after all data are read into the buffer. */
{
- int gap_size = GAP_SIZE;
+ EMACS_INT gap_size = GAP_SIZE;
while (how_much < total)
{
/* try is reserved in some compilers (Microsoft C) */
- int trytry = min (total - how_much, READ_BUF_SIZE);
- int this;
+ EMACS_INT trytry = min (total - how_much, READ_BUF_SIZE);
+ EMACS_INT this;
if (not_regular)
{
}
SAVE_MODIFF = MODIFF;
- current_buffer->auto_save_modified = MODIFF;
+ BUF_AUTOSAVE_MODIFF (current_buffer) = MODIFF;
XSETFASTINT (current_buffer->save_length, Z - BEG);
#ifdef CLASH_DETECTION
if (NILP (handler))
{
/* Don't run point motion or modification hooks when decoding. */
int count = SPECPDL_INDEX ();
- int old_inserted = inserted;
+ EMACS_INT old_inserted = inserted;
specbind (Qinhibit_point_motion_hooks, Qt);
specbind (Qinhibit_modification_hooks, Qt);
Hence we temporarily save `point' and `inserted' here and
restore `point' iff format-decode did not insert or delete
any text. Otherwise we leave `point' at point-min. */
- int opoint = PT;
- int opoint_byte = PT_BYTE;
- int oinserted = ZV - BEGV;
+ EMACS_INT opoint = PT;
+ EMACS_INT opoint_byte = PT_BYTE;
+ EMACS_INT oinserted = ZV - BEGV;
int ochars_modiff = CHARS_MODIFF;
TEMP_SET_PT_BOTH (BEGV, BEGV_BYTE);
{
/* For the rationale of this see the comment on
format-decode above. */
- int opoint = PT;
- int opoint_byte = PT_BYTE;
- int oinserted = ZV - BEGV;
+ EMACS_INT opoint = PT;
+ EMACS_INT opoint_byte = PT_BYTE;
+ EMACS_INT oinserted = ZV - BEGV;
int ochars_modiff = CHARS_MODIFF;
TEMP_SET_PT_BOTH (BEGV, BEGV_BYTE);
\f
static Lisp_Object build_annotations P_ ((Lisp_Object, Lisp_Object));
-/* If build_annotations switched buffers, switch back to BUF.
- Kill the temporary buffer that was selected in the meantime.
-
- Since this kill only the last temporary buffer, some buffers remain
- not killed if build_annotations switched buffers more than once.
- -- K.Handa */
-
static Lisp_Object
-build_annotations_unwind (buf)
- Lisp_Object buf;
+build_annotations_unwind (arg)
+ Lisp_Object arg;
{
- Lisp_Object tembuf;
-
- if (XBUFFER (buf) == current_buffer)
- return Qnil;
- tembuf = Fcurrent_buffer ();
- Fset_buffer (buf);
- Fkill_buffer (tembuf);
+ Vwrite_region_annotation_buffers = arg;
return Qnil;
}
This does code conversion according to the value of
`coding-system-for-write', `buffer-file-coding-system', or
`file-coding-system-alist', and sets the variable
-`last-coding-system-used' to the coding system actually used. */)
+`last-coding-system-used' to the coding system actually used.
+
+This calls `write-region-annotate-functions' at the start, and
+`write-region-post-annotation-function' at the end. */)
(start, end, filename, append, visit, lockname, mustbenew)
Lisp_Object start, end, filename, append, visit, lockname, mustbenew;
{
Fwiden ();
}
- record_unwind_protect (build_annotations_unwind, Fcurrent_buffer ());
+ record_unwind_protect (build_annotations_unwind,
+ Vwrite_region_annotation_buffers);
+ Vwrite_region_annotation_buffers = Fcons (Fcurrent_buffer (), Qnil);
count1 = SPECPDL_INDEX ();
given_buffer = current_buffer;
#ifdef CLASH_DETECTION
if (!auto_saving)
- {
-#if 0 /* This causes trouble for GNUS. */
- /* If we've locked this file for some other buffer,
- query before proceeding. */
- if (!visiting && EQ (Ffile_locked_p (lockname), Qt))
- call2 (intern ("ask-user-about-lock"), filename, Vuser_login_name);
-#endif
-
- lock_file (lockname);
- }
+ lock_file (lockname);
#endif /* CLASH_DETECTION */
encoded_filename = ENCODE_FILE (filename);
UNGCPRO;
-#if 0
- /* The new encoding routine doesn't require the following. */
-
- /* Whether VMS or not, we must move the gap to the next of newline
- when we must put designation sequences at beginning of line. */
- if (INTEGERP (start)
- && coding.type == coding_type_iso2022
- && coding.flags & CODING_FLAG_ISO_DESIGNATE_AT_BOL
- && GPT > BEG && GPT_ADDR[-1] != '\n')
- {
- int opoint = PT, opoint_byte = PT_BYTE;
- scan_newline (PT, PT_BYTE, ZV, ZV_BYTE, 1, 0);
- move_gap_both (PT, PT_BYTE);
- SET_PT_BOTH (opoint, opoint_byte);
- }
-#endif
-
failure = 0;
immediate_quit = 1;
}
#endif
- /* Spurious "file has changed on disk" warnings have been
- observed on Suns as well.
- It seems that `close' can change the modtime, under nfs.
-
- (This has supposedly been fixed in Sunos 4,
- but who knows about all the other machines with NFS?) */
-#if 0
-
-#define FOO
- fstat (desc, &st);
-#endif
-
/* NFS can report a write failure now. */
if (emacs_close (desc) < 0)
failure = 1, save_errno = errno;
-#ifndef FOO
stat (fn, &st);
-#endif
+
/* Discard the unwind protect for close_file_unwind. */
specpdl_ptr = specpdl + count1;
- /* Restore the original current buffer. */
- visit_file = unbind_to (count, visit_file);
+
+ /* Call write-region-post-annotation-function. */
+ while (CONSP (Vwrite_region_annotation_buffers))
+ {
+ Lisp_Object buf = XCAR (Vwrite_region_annotation_buffers);
+ if (!NILP (Fbuffer_live_p (buf)))
+ {
+ Fset_buffer (buf);
+ if (FUNCTIONP (Vwrite_region_post_annotation_function))
+ call0 (Vwrite_region_post_annotation_function);
+ }
+ Vwrite_region_annotation_buffers
+ = XCDR (Vwrite_region_annotation_buffers);
+ }
+
+ unbind_to (count, Qnil);
#ifdef CLASH_DETECTION
if (!auto_saving)
been dealt with by this function. */
if (current_buffer != given_buffer)
{
+ Vwrite_region_annotation_buffers
+ = Fcons (Fcurrent_buffer (),
+ Vwrite_region_annotation_buffers);
XSETFASTINT (start, BEGV);
XSETFASTINT (end, ZV);
annotations = Qnil;
and file changed since last real save. */
if (STRINGP (b->auto_save_file_name)
&& BUF_SAVE_MODIFF (b) < BUF_MODIFF (b)
- && b->auto_save_modified < BUF_MODIFF (b)
+ && BUF_AUTOSAVE_MODIFF (b) < BUF_MODIFF (b)
/* -1 means we've turned off autosaving for a while--see below. */
&& XINT (b->save_length) >= 0
&& (do_handled_files
&& EMACS_SECS (before_time) - b->auto_save_failure_time < 1200)
continue;
- if ((XFASTINT (b->save_length) * 10
- > (BUF_Z (b) - BUF_BEG (b)) * 13)
+ set_buffer_internal (b);
+ if (NILP (Vauto_save_include_big_deletions)
+ && (XFASTINT (b->save_length) * 10
+ > (BUF_Z (b) - BUF_BEG (b)) * 13)
/* A short file is likely to change a large fraction;
spare the user annoying messages. */
&& XFASTINT (b->save_length) > 5000
Fsleep_for (make_number (1), Qnil);
continue;
}
- set_buffer_internal (b);
if (!auto_saved && NILP (no_message))
message1 ("Auto-saving...");
internal_condition_case (auto_save_1, Qt, auto_save_error);
auto_saved++;
- b->auto_save_modified = BUF_MODIFF (b);
+ BUF_AUTOSAVE_MODIFF (b) = BUF_MODIFF (b);
XSETFASTINT (current_buffer->save_length, Z - BEG);
set_buffer_internal (old);
No auto-save file will be written until the buffer changes again. */)
()
{
- current_buffer->auto_save_modified = MODIFF;
+ /* FIXME: This should not be called in indirect buffers, since
+ they're not autosaved. */
+ BUF_AUTOSAVE_MODIFF (current_buffer) = MODIFF;
XSETFASTINT (current_buffer->save_length, Z - BEG);
current_buffer->auto_save_failure_time = -1;
return Qnil;
then any auto-save counts as "recent". */)
()
{
- return (SAVE_MODIFF < current_buffer->auto_save_modified) ? Qt : Qnil;
+ /* FIXME: maybe we should return nil for indirect buffers since
+ they're never autosaved. */
+ return (SAVE_MODIFF < BUF_AUTOSAVE_MODIFF (current_buffer) ? Qt : Qnil);
}
\f
/* Reading and completing file names */
Snext_read_file_uses_dialog_p, 0, 0, 0,
doc: /* Return t if a call to `read-file-name' will use a dialog.
The return value is only relevant for a call to `read-file-name' that happens
-before any other event (mouse or keypress) is handeled. */)
+before any other event (mouse or keypress) is handled. */)
()
{
#if defined (USE_MOTIF) || defined (HAVE_NTGUI) || defined (USE_GTK)
}
\f
-void
-init_fileio_once ()
-{
- /* Must be set before any path manipulation is performed. */
- XSETFASTINT (Vdirectory_sep_char, '/');
-}
-
-\f
void
syms_of_fileio ()
{
- Qoperations = intern ("operations");
- Qexpand_file_name = intern ("expand-file-name");
- Qsubstitute_in_file_name = intern ("substitute-in-file-name");
- Qdirectory_file_name = intern ("directory-file-name");
- Qfile_name_directory = intern ("file-name-directory");
- Qfile_name_nondirectory = intern ("file-name-nondirectory");
- Qunhandled_file_name_directory = intern ("unhandled-file-name-directory");
- Qfile_name_as_directory = intern ("file-name-as-directory");
- Qcopy_file = intern ("copy-file");
- Qmake_directory_internal = intern ("make-directory-internal");
- Qmake_directory = intern ("make-directory");
- Qdelete_directory = intern ("delete-directory");
- Qdelete_file = intern ("delete-file");
- Qrename_file = intern ("rename-file");
- Qadd_name_to_file = intern ("add-name-to-file");
- Qmake_symbolic_link = intern ("make-symbolic-link");
- Qfile_exists_p = intern ("file-exists-p");
- Qfile_executable_p = intern ("file-executable-p");
- Qfile_readable_p = intern ("file-readable-p");
- Qfile_writable_p = intern ("file-writable-p");
- Qfile_symlink_p = intern ("file-symlink-p");
- Qaccess_file = intern ("access-file");
- Qfile_directory_p = intern ("file-directory-p");
- Qfile_regular_p = intern ("file-regular-p");
- Qfile_accessible_directory_p = intern ("file-accessible-directory-p");
- Qfile_modes = intern ("file-modes");
- Qset_file_modes = intern ("set-file-modes");
- Qset_file_times = intern ("set-file-times");
- Qfile_newer_than_file_p = intern ("file-newer-than-file-p");
- Qinsert_file_contents = intern ("insert-file-contents");
- Qwrite_region = intern ("write-region");
- Qverify_visited_file_modtime = intern ("verify-visited-file-modtime");
- Qset_visited_file_modtime = intern ("set-visited-file-modtime");
- Qauto_save_coding = intern ("auto-save-coding");
+ Qoperations = intern_c_string ("operations");
+ Qexpand_file_name = intern_c_string ("expand-file-name");
+ Qsubstitute_in_file_name = intern_c_string ("substitute-in-file-name");
+ Qdirectory_file_name = intern_c_string ("directory-file-name");
+ Qfile_name_directory = intern_c_string ("file-name-directory");
+ Qfile_name_nondirectory = intern_c_string ("file-name-nondirectory");
+ Qunhandled_file_name_directory = intern_c_string ("unhandled-file-name-directory");
+ Qfile_name_as_directory = intern_c_string ("file-name-as-directory");
+ Qcopy_file = intern_c_string ("copy-file");
+ Qmake_directory_internal = intern_c_string ("make-directory-internal");
+ Qmake_directory = intern_c_string ("make-directory");
+ Qdelete_directory_internal = intern_c_string ("delete-directory-internal");
+ Qdelete_file = intern_c_string ("delete-file");
+ Qrename_file = intern_c_string ("rename-file");
+ Qadd_name_to_file = intern_c_string ("add-name-to-file");
+ Qmake_symbolic_link = intern_c_string ("make-symbolic-link");
+ Qfile_exists_p = intern_c_string ("file-exists-p");
+ Qfile_executable_p = intern_c_string ("file-executable-p");
+ Qfile_readable_p = intern_c_string ("file-readable-p");
+ Qfile_writable_p = intern_c_string ("file-writable-p");
+ Qfile_symlink_p = intern_c_string ("file-symlink-p");
+ Qaccess_file = intern_c_string ("access-file");
+ Qfile_directory_p = intern_c_string ("file-directory-p");
+ Qfile_regular_p = intern_c_string ("file-regular-p");
+ Qfile_accessible_directory_p = intern_c_string ("file-accessible-directory-p");
+ Qfile_modes = intern_c_string ("file-modes");
+ Qset_file_modes = intern_c_string ("set-file-modes");
+ Qset_file_times = intern_c_string ("set-file-times");
+ Qfile_newer_than_file_p = intern_c_string ("file-newer-than-file-p");
+ Qinsert_file_contents = intern_c_string ("insert-file-contents");
+ Qwrite_region = intern_c_string ("write-region");
+ Qverify_visited_file_modtime = intern_c_string ("verify-visited-file-modtime");
+ Qset_visited_file_modtime = intern_c_string ("set-visited-file-modtime");
+ Qauto_save_coding = intern_c_string ("auto-save-coding");
staticpro (&Qoperations);
staticpro (&Qexpand_file_name);
staticpro (&Qcopy_file);
staticpro (&Qmake_directory_internal);
staticpro (&Qmake_directory);
- staticpro (&Qdelete_directory);
+ staticpro (&Qdelete_directory_internal);
staticpro (&Qdelete_file);
staticpro (&Qrename_file);
staticpro (&Qadd_name_to_file);
staticpro (&Qset_visited_file_modtime);
staticpro (&Qauto_save_coding);
- Qfile_name_history = intern ("file-name-history");
+ Qfile_name_history = intern_c_string ("file-name-history");
Fset (Qfile_name_history, Qnil);
staticpro (&Qfile_name_history);
- Qfile_error = intern ("file-error");
+ Qfile_error = intern_c_string ("file-error");
staticpro (&Qfile_error);
- Qfile_already_exists = intern ("file-already-exists");
+ Qfile_already_exists = intern_c_string ("file-already-exists");
staticpro (&Qfile_already_exists);
- Qfile_date_error = intern ("file-date-error");
+ Qfile_date_error = intern_c_string ("file-date-error");
staticpro (&Qfile_date_error);
- Qexcl = intern ("excl");
+ Qexcl = intern_c_string ("excl");
staticpro (&Qexcl);
#ifdef DOS_NT
- Qfind_buffer_file_type = intern ("find-buffer-file-type");
+ Qfind_buffer_file_type = intern_c_string ("find-buffer-file-type");
staticpro (&Qfind_buffer_file_type);
#endif /* DOS_NT */
of file names regardless of the current language environment. */);
Vdefault_file_name_coding_system = Qnil;
- Qformat_decode = intern ("format-decode");
+ Qformat_decode = intern_c_string ("format-decode");
staticpro (&Qformat_decode);
- Qformat_annotate_function = intern ("format-annotate-function");
+ Qformat_annotate_function = intern_c_string ("format-annotate-function");
staticpro (&Qformat_annotate_function);
- Qafter_insert_file_set_coding = intern ("after-insert-file-set-coding");
+ Qafter_insert_file_set_coding = intern_c_string ("after-insert-file-set-coding");
staticpro (&Qafter_insert_file_set_coding);
- Qcar_less_than_car = intern ("car-less-than-car");
+ Qcar_less_than_car = intern_c_string ("car-less-than-car");
staticpro (&Qcar_less_than_car);
Fput (Qfile_error, Qerror_conditions,
- list2 (Qfile_error, Qerror));
+ Fpurecopy (list2 (Qfile_error, Qerror)));
Fput (Qfile_error, Qerror_message,
- build_string ("File error"));
+ make_pure_c_string ("File error"));
Fput (Qfile_already_exists, Qerror_conditions,
- list3 (Qfile_already_exists, Qfile_error, Qerror));
+ Fpurecopy (list3 (Qfile_already_exists, Qfile_error, Qerror)));
Fput (Qfile_already_exists, Qerror_message,
- build_string ("File already exists"));
+ make_pure_c_string ("File already exists"));
Fput (Qfile_date_error, Qerror_conditions,
- list3 (Qfile_date_error, Qfile_error, Qerror));
+ Fpurecopy (list3 (Qfile_date_error, Qfile_error, Qerror)));
Fput (Qfile_date_error, Qerror_message,
- build_string ("Cannot set file date"));
+ make_pure_c_string ("Cannot set file date"));
DEFVAR_LISP ("directory-sep-char", &Vdirectory_sep_char,
doc: /* Directory separator character for built-in functions that return file names.
The value is always ?/. Don't use this variable, just use `/'. */);
+ XSETFASTINT (Vdirectory_sep_char, '/');
DEFVAR_LISP ("file-name-handler-alist", &Vfile_name_handler_alist,
doc: /* *Alist of elements (REGEXP . HANDLER) for file names handled specially.
of the form (POSITION . STRING), consisting of strings to be effectively
inserted at the specified positions of the file being written (1 means to
insert before the first byte written). The POSITIONs must be sorted into
-increasing order. If there are several functions in the list, the several
-lists are merged destructively. Alternatively, the function can return
-with a different buffer current; in that case it should pay attention
-to the annotations returned by previous functions and listed in
-`write-region-annotations-so-far'.*/);
+increasing order.
+
+If there are several annotation functions, the lists returned by these
+functions are merged destructively. As each annotation function runs,
+the variable `write-region-annotations-so-far' contains a list of all
+annotations returned by previous annotation functions.
+
+An annotation function can return with a different buffer current.
+Doing so removes the annotations returned by previous functions, and
+resets START and END to `point-min' and `point-max' of the new buffer.
+
+After `write-region' completes, Emacs calls the function stored in
+`write-region-post-annotation-function', once for each buffer that was
+current when building the annotations (i.e., at least once), with that
+buffer current. */);
Vwrite_region_annotate_functions = Qnil;
staticpro (&Qwrite_region_annotate_functions);
Qwrite_region_annotate_functions
- = intern ("write-region-annotate-functions");
+ = intern_c_string ("write-region-annotate-functions");
+
+ DEFVAR_LISP ("write-region-post-annotation-function",
+ &Vwrite_region_post_annotation_function,
+ doc: /* Function to call after `write-region' completes.
+The function is called with no arguments. If one or more of the
+annotation functions in `write-region-annotate-functions' changed the
+current buffer, the function stored in this variable is called for
+each of those additional buffers as well, in addition to the original
+buffer. The relevant buffer is current during each function call. */);
+ Vwrite_region_post_annotation_function = Qnil;
+ staticpro (&Vwrite_region_annotation_buffers);
DEFVAR_LISP ("write-region-annotations-so-far",
&Vwrite_region_annotations_so_far,
Normally auto-save files are written under other names. */);
Vauto_save_visited_file_name = Qnil;
+ DEFVAR_LISP ("auto-save-include-big-deletions", &Vauto_save_include_big_deletions,
+ doc: /* If non-nil, auto-save even if a large part of the text is deleted.
+If nil, deleting a substantial portion of the text disables auto-save
+in the buffer; this is the default behavior, because the auto-save
+file is usually more useful if it contains the deleted text. */);
+ Vauto_save_include_big_deletions = Qnil;
+
#ifdef HAVE_FSYNC
DEFVAR_BOOL ("write-region-inhibit-fsync", &write_region_inhibit_fsync,
doc: /* *Non-nil means don't call fsync in `write-region'.
When non-nil, the function `move-file-to-trash' will be used by
`delete-file' and `delete-directory'. */);
delete_by_moving_to_trash = 0;
- Qdelete_by_moving_to_trash = intern ("delete-by-moving-to-trash");
- Qmove_file_to_trash = intern ("move-file-to-trash");
+ Qdelete_by_moving_to_trash = intern_c_string ("delete-by-moving-to-trash");
+ Qmove_file_to_trash = intern_c_string ("move-file-to-trash");
staticpro (&Qmove_file_to_trash);
defsubr (&Sfind_file_name_handler);
defsubr (&Ssubstitute_in_file_name);
defsubr (&Scopy_file);
defsubr (&Smake_directory_internal);
- defsubr (&Sdelete_directory);
+ defsubr (&Sdelete_directory_internal);
defsubr (&Sdelete_file);
defsubr (&Srename_file);
defsubr (&Sadd_name_to_file);