X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/bd2356104120d8744b74743f4d05f91c7e37c50e..ffe8b3f4e8cf60dd97c3e5ec5f12183ad9006c02:/src/fileio.c diff --git a/src/fileio.c b/src/fileio.c index 71036912bb..c0195558a3 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -1,5 +1,5 @@ /* File IO for GNU Emacs. - Copyright (C) 1985,86,87,88,93,94,95,96,97,98,99,2000, 2001 + Copyright (C) 1985,86,87,88,93,94,95,96,97,98,99,2000,01,2003 Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -134,6 +134,7 @@ extern int errno; #include "commands.h" extern int use_dialog_box; +extern int use_file_dialog; #ifndef O_WRONLY #define O_WRONLY 1 @@ -154,6 +155,13 @@ int auto_saving; a new file with the same mode as the original */ int auto_save_mode_bits; +/* The symbol bound to coding-system-for-read when + insert-file-contents is called for recovering a file. This is not + an actual coding system name, but just an indicator to tell + insert-file-contents to use `emacs-mule' with a special flag for + auto saving and recovering a file. */ +Lisp_Object Qauto_save_coding; + /* Coding system for file names, or nil if none. */ Lisp_Object Vfile_name_coding_system; @@ -2379,7 +2387,8 @@ A number as third arg means request confirmation if NEWNAME already exists. This is what happens in interactive use with M-x. Fourth arg KEEP-TIME non-nil means give the new file the same last-modified time as the old one. (This works on only some systems.) -A prefix arg makes KEEP-TIME non-nil. */) +A prefix arg makes KEEP-TIME non-nil. +Also set the file modes of the target file to match the source file. */) (file, newname, ok_if_already_exists, keep_time) Lisp_Object file, newname, ok_if_already_exists, keep_time; { @@ -2398,7 +2407,7 @@ A prefix arg makes KEEP-TIME non-nil. */) CHECK_STRING (newname); if (!NILP (Ffile_directory_p (newname))) - newname = Fexpand_file_name (file, newname); + newname = Fexpand_file_name (Ffile_name_nondirectory (file), newname); else newname = Fexpand_file_name (newname, Qnil); @@ -2623,7 +2632,8 @@ If file has multiple names, it continues to exist with the other names. */) struct gcpro gcpro1; GCPRO1 (filename); - if (!NILP (Ffile_directory_p (filename))) + if (!NILP (Ffile_directory_p (filename)) + && NILP (Ffile_symlink_p (filename))) Fsignal (Qfile_error, Fcons (build_string ("Removing old name: is a directory"), Fcons (filename, Qnil))); @@ -3192,11 +3202,6 @@ Otherwise returns nil. */) (filename) Lisp_Object filename; { -#ifdef S_IFLNK - char *buf; - int bufsize; - int valsize; - Lisp_Object val; Lisp_Object handler; CHECK_STRING (filename); @@ -3208,6 +3213,13 @@ Otherwise returns nil. */) if (!NILP (handler)) return call2 (handler, Qfile_symlink_p, filename); +#ifdef S_IFLNK + { + char *buf; + int bufsize; + int valsize; + Lisp_Object val; + filename = ENCODE_FILE (filename); bufsize = 50; @@ -3242,6 +3254,7 @@ Otherwise returns nil. */) xfree (buf); val = DECODE_FILE (val); return val; + } #else /* not S_IFLNK */ return Qnil; #endif /* not S_IFLNK */ @@ -3760,7 +3773,20 @@ actually used. */) } } - if (BEG < Z) + if (EQ (Vcoding_system_for_read, Qauto_save_coding)) + { + /* We use emacs-mule for auto saving... */ + setup_coding_system (Qemacs_mule, &coding); + /* ... but with the special flag to indicate to read in a + multibyte sequence for eight-bit-control char as is. */ + coding.flags = 1; + coding.src_multibyte = 0; + coding.dst_multibyte + = !NILP (current_buffer->enable_multibyte_characters); + coding.eol_type = CODING_EOL_LF; + coding_system_decided = 1; + } + else if (BEG < Z) { /* Decide the coding system to use for reading the file now because we can't use an optimized method for handling @@ -3815,12 +3841,13 @@ actually used. */) buffer = Fget_buffer_create (build_string (" *code-converting-work*")); buf = XBUFFER (buffer); + delete_all_overlays (buf); buf->directory = current_buffer->directory; buf->read_only = Qnil; buf->filename = Qnil; buf->undo_list = Qt; - buf->overlays_before = Qnil; - buf->overlays_after = Qnil; + eassert (buf->overlays_before == NULL); + eassert (buf->overlays_after == NULL); set_buffer_internal (buf); Ferase_buffer (); @@ -4658,8 +4685,17 @@ choose_write_coding_system (start, end, filename, { Lisp_Object val; - if (auto_saving) - val = Qnil; + if (auto_saving + && NILP (Fstring_equal (current_buffer->filename, + current_buffer->auto_save_file_name))) + { + /* We use emacs-mule for auto saving... */ + setup_coding_system (Qemacs_mule, coding); + /* ... but with the special flag to indicate not to strip off + leading code of eight-bit-control chars. */ + coding->flags = 1; + goto done_setup_coding; + } else if (!NILP (Vcoding_system_for_write)) { val = Vcoding_system_for_write; @@ -4861,11 +4897,14 @@ This does code conversion according to the value of return val; } + record_unwind_protect (save_restriction_restore, save_restriction_save ()); + /* Special kludge to simplify auto-saving. */ if (NILP (start)) { XSETFASTINT (start, BEG); XSETFASTINT (end, Z); + Fwiden (); } record_unwind_protect (build_annotations_unwind, Fcurrent_buffer ()); @@ -5184,10 +5223,22 @@ This does code conversion according to the value of update_mode_lines++; } else if (quietly) - return Qnil; + { + if (auto_saving + && ! NILP (Fstring_equal (current_buffer->filename, + current_buffer->auto_save_file_name))) + SAVE_MODIFF = MODIFF; + + return Qnil; + } if (!auto_saving) - message_with_string ("Wrote %s", visit_file, 1); + message_with_string ((INTEGERP (append) + ? "Updated %s" + : ! NILP (append) + ? "Added to %s" + : "Wrote %s"), + visit_file, 1); return Qnil; } @@ -5458,7 +5509,8 @@ e_write (desc, string, start, end, coding) DEFUN ("verify-visited-file-modtime", Fverify_visited_file_modtime, Sverify_visited_file_modtime, 1, 1, 0, doc: /* Return t if last mod time of BUF's visited file matches what BUF records. -This means that the file has not been changed since it was visited or saved. */) +This means that the file has not been changed since it was visited or saved. +See Info node `(elisp)Modification Time' for more details. */) (buf) Lisp_Object buf; { @@ -5514,7 +5566,9 @@ DEFUN ("visited-file-modtime", Fvisited_file_modtime, Svisited_file_modtime, 0, 0, 0, doc: /* Return the current buffer's recorded visited file modification time. The value is a list of the form (HIGH . LOW), like the time values -that `file-attributes' returns. */) +that `file-attributes' returns. If the current buffer has no recorded +file modification time, this function returns 0. +See Info node `(elisp)Modification Time' for more details. */) () { return long_to_cons ((unsigned long) current_buffer->modtime); @@ -5734,11 +5788,14 @@ A non-nil CURRENT-ONLY argument means save only current buffer. */) minibuffer_auto_raise = 0; auto_saving = 1; - /* First, save all files which don't have handlers. If Emacs is - crashing, the handlers may tweak what is causing Emacs to crash - in the first place, and it would be a shame if Emacs failed to - autosave perfectly ordinary files because it couldn't handle some - ange-ftp'd file. */ + /* On first pass, save all files that don't have handlers. + On second pass, save all files that do have handlers. + + If Emacs is crashing, the handlers may tweak what is causing + Emacs to crash in the first place, and it would be a shame if + Emacs failed to autosave perfectly ordinary files because it + couldn't handle some ange-ftp'd file. */ + for (do_handled_files = 0; do_handled_files < 2; do_handled_files++) for (tail = Vbuffer_alist; GC_CONSP (tail); tail = XCDR (tail)) { @@ -6041,6 +6098,7 @@ DEFUN ("read-file-name-internal", Fread_file_name_internal, Sread_file_name_inte if (SCHARS (name) == 0) return Qt; #endif /* VMS */ + string = Fexpand_file_name (string, dir); if (!NILP (Vread_file_name_predicate)) return call1 (Vread_file_name_predicate, string); return Ffile_exists_p (string); @@ -6049,15 +6107,20 @@ DEFUN ("read-file-name-internal", Fread_file_name_internal, Sread_file_name_inte DEFUN ("read-file-name", Fread_file_name, Sread_file_name, 1, 6, 0, doc: /* Read file name, prompting with PROMPT and completing in directory DIR. Value is not expanded---you must call `expand-file-name' yourself. -Default name to DEFAULT-FILENAME if user enters a null string. +Default name to DEFAULT-FILENAME if user exits the minibuffer with +the same non-empty string that was inserted by this function. (If DEFAULT-FILENAME is omitted, the visited file name is used, except that if INITIAL is specified, that combined with DIR is used.) +If the user exits with an empty minibuffer, this function returns +an empty string. (This can only happen if the user erased the +pre-inserted contents or if `insert-default-directory' is nil.) Fourth arg MUSTMATCH non-nil means require existing file's name. Non-nil and non-t means also require confirmation after completion. Fifth arg INITIAL specifies text to start with. -If optional sixth arg PREDICATE is non-nil, possible completions and the -resulting file name must satisfy (funcall PREDICATE NAME). -DIR defaults to current buffer's directory default. +If optional sixth arg PREDICATE is non-nil, possible completions and +the resulting file name must satisfy (funcall PREDICATE NAME). +DIR should be an absolute directory name. It defaults to the value of +`default-directory'. If this command was invoked with the mouse, use a file dialog box if `use-dialog-box' is non-nil, and the window system or X toolkit in use @@ -6158,7 +6221,7 @@ provides a file dialog box. */) } count = SPECPDL_INDEX (); -#ifdef VMS +#if defined VMS || defined DOS_NT || defined MAC_OSX specbind (intern ("completion-ignore-case"), Qt); #endif @@ -6171,6 +6234,7 @@ provides a file dialog box. */) #if defined (USE_MOTIF) || defined (HAVE_NTGUI) || defined (USE_GTK) if ((NILP (last_nonmenu_event) || CONSP (last_nonmenu_event)) && use_dialog_box + && use_file_dialog && have_menus_p ()) { /* If DIR contains a file name, split it. */ @@ -6220,13 +6284,6 @@ provides a file dialog box. */) if (!NILP (tem) && !NILP (default_filename)) val = default_filename; - else if (SCHARS (val) == 0 && NILP (insdef)) - { - if (!NILP (default_filename)) - val = default_filename; - else - error ("No default file name"); - } val = Fsubstitute_in_file_name (val); if (replace_in_history) @@ -6290,6 +6347,7 @@ syms_of_fileio () 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"); staticpro (&Qexpand_file_name); staticpro (&Qsubstitute_in_file_name); @@ -6322,6 +6380,7 @@ syms_of_fileio () staticpro (&Qwrite_region); staticpro (&Qverify_visited_file_modtime); staticpro (&Qset_visited_file_modtime); + staticpro (&Qauto_save_coding); Qfile_name_history = intern ("file-name-history"); Fset (Qfile_name_history, Qnil); @@ -6400,7 +6459,20 @@ same format as a regular save would use. */); Vread_file_name_predicate = Qnil; DEFVAR_BOOL ("insert-default-directory", &insert_default_directory, - doc: /* *Non-nil means when reading a filename start with default dir in minibuffer. */); + doc: /* *Non-nil means when reading a filename start with default dir in minibuffer. +If the initial minibuffer contents are non-empty, you can usually +request a default filename by typing RETURN without editing. For some +commands, exiting with an empty minibuffer has a special meaning, +such as making the current buffer visit no file in the case of +`set-visited-file-name'. +If this variable is non-nil, the minibuffer contents are always +initially non-empty and typing RETURN without editing will fetch the +default name, if one is provided. Note however that this default name +is not necessarily the name originally inserted in the minibuffer, if +that is just the default directory. +If this variable is nil, the minibuffer often starts out empty. In +that case you may have to explicitly fetch the next history element to +request the default name. */); insert_default_directory = 1; DEFVAR_BOOL ("vms-stmlf-recfm", &vms_stmlf_recfm, @@ -6548,3 +6620,6 @@ a non-nil value. */); defsubr (&Sunix_sync); #endif } + +/* arch-tag: 64ba3fd7-f844-4fb2-ba4b-427eb928786c + (do not change this comment) */