- register char *homedir;
- Lisp_Object decoded_homedir;
- int replace_in_history = 0;
- int add_to_history = 0;
- int count;
-
- if (NILP (dir))
- dir = current_buffer->directory;
- if (NILP (Ffile_name_absolute_p (dir)))
- dir = Fexpand_file_name (dir, Qnil);
- if (NILP (default_filename))
- default_filename
- = (!NILP (initial)
- ? Fexpand_file_name (initial, dir)
- : current_buffer->filename);
-
- /* If dir starts with user's homedir, change that to ~. */
- homedir = (char *) egetenv ("HOME");
-#ifdef DOS_NT
- /* homedir can be NULL in temacs, since Vglobal_environment is not
- yet set up. We shouldn't crash in that case. */
- if (homedir != 0)
- {
- homedir = strcpy (alloca (strlen (homedir) + 1), homedir);
- CORRECT_DIR_SEPS (homedir);
- }
-#endif
- if (homedir != 0)
- decoded_homedir
- = DECODE_FILE (make_unibyte_string (homedir, strlen (homedir)));
- if (homedir != 0
- && STRINGP (dir)
- && !strncmp (SDATA (decoded_homedir), SDATA (dir),
- SBYTES (decoded_homedir))
- && IS_DIRECTORY_SEP (SREF (dir, SBYTES (decoded_homedir))))
- {
- dir = Fsubstring (dir, make_number (SCHARS (decoded_homedir)), Qnil);
- dir = concat2 (build_string ("~"), dir);
- }
- /* Likewise for default_filename. */
- if (homedir != 0
- && STRINGP (default_filename)
- && !strncmp (SDATA (decoded_homedir), SDATA (default_filename),
- SBYTES (decoded_homedir))
- && IS_DIRECTORY_SEP (SREF (default_filename, SBYTES (decoded_homedir))))
- {
- default_filename
- = Fsubstring (default_filename,
- make_number (SCHARS (decoded_homedir)), Qnil);
- default_filename = concat2 (build_string ("~"), default_filename);
- }
- if (!NILP (default_filename))
- {
- CHECK_STRING (default_filename);
- default_filename = double_dollars (default_filename);
- }
-
- if (insert_default_directory && STRINGP (dir))
- {
- insdef = dir;
- if (!NILP (initial))
- {
- Lisp_Object args[2], pos;
-
- args[0] = insdef;
- args[1] = initial;
- insdef = Fconcat (2, args);
- pos = make_number (SCHARS (double_dollars (dir)));
- insdef = Fcons (double_dollars (insdef), pos);
- }
- else
- insdef = double_dollars (insdef);
- }
- else if (STRINGP (initial))
- insdef = Fcons (double_dollars (initial), make_number (0));
- else
- insdef = Qnil;
-
- if (!NILP (Vread_file_name_function))
- {
- Lisp_Object args[7];
-
- GCPRO2 (insdef, default_filename);
- args[0] = Vread_file_name_function;
- args[1] = prompt;
- args[2] = dir;
- args[3] = default_filename;
- args[4] = mustmatch;
- args[5] = initial;
- args[6] = predicate;
- RETURN_UNGCPRO (Ffuncall (7, args));
- }
-
- count = SPECPDL_INDEX ();
- specbind (Qcompletion_ignore_case,
- read_file_name_completion_ignore_case ? Qt : Qnil);
- specbind (intern ("minibuffer-completing-file-name"), Qt);
- specbind (intern ("read-file-name-predicate"),
- (NILP (predicate) ? Qfile_exists_p : predicate));
-
- GCPRO2 (insdef, default_filename);
-
-#if defined (USE_MOTIF) || defined (HAVE_NTGUI) || defined (USE_GTK) || defined (HAVE_CARBON)
- if (! NILP (Fnext_read_file_uses_dialog_p ()))
- {
- /* If DIR contains a file name, split it. */
- Lisp_Object file;
- file = Ffile_name_nondirectory (dir);
- if (SCHARS (file) && NILP (default_filename))
- {
- default_filename = file;
- dir = Ffile_name_directory (dir);
- }
- if (!NILP(default_filename))
- default_filename = Fexpand_file_name (default_filename, dir);
- val = Fx_file_dialog (prompt, dir, default_filename, mustmatch,
- EQ (predicate, Qfile_directory_p) ? Qt : Qnil);
- add_to_history = 1;
- }
- else
-#endif
- val = Fcompleting_read (prompt, intern ("read-file-name-internal"),
- dir, mustmatch, insdef,
- Qfile_name_history, default_filename, Qnil);
-
- tem = Fsymbol_value (Qfile_name_history);
- if (CONSP (tem) && EQ (XCAR (tem), val))
- replace_in_history = 1;
-
- /* If Fcompleting_read returned the inserted default string itself
- (rather than a new string with the same contents),
- it has to mean that the user typed RET with the minibuffer empty.
- In that case, we really want to return ""
- so that commands such as set-visited-file-name can distinguish. */
- if (EQ (val, default_filename))
- {
- /* In this case, Fcompleting_read has not added an element
- to the history. Maybe we should. */
- if (! replace_in_history)
- add_to_history = 1;
-
- val = empty_unibyte_string;
- }
-
- unbind_to (count, Qnil);
- UNGCPRO;
- if (NILP (val))
- error ("No file name specified");
-
- tem = Fstring_equal (val, CONSP (insdef) ? XCAR (insdef) : insdef);
-
- if (!NILP (tem) && !NILP (default_filename))
- val = default_filename;
- val = Fsubstitute_in_file_name (val);
-
- if (replace_in_history)
- /* Replace what Fcompleting_read added to the history
- with what we will actually return. */
- {
- Lisp_Object val1 = double_dollars (val);
- tem = Fsymbol_value (Qfile_name_history);
- if (history_delete_duplicates)
- XSETCDR (tem, Fdelete (val1, XCDR(tem)));
- XSETCAR (tem, val1);
- }
- else if (add_to_history)
- {
- /* Add the value to the history--but not if it matches
- the last value already there. */
- Lisp_Object val1 = double_dollars (val);
- tem = Fsymbol_value (Qfile_name_history);
- if (! CONSP (tem) || NILP (Fequal (XCAR (tem), val1)))
- {
- if (history_delete_duplicates) tem = Fdelete (val1, tem);
- Fset (Qfile_name_history, Fcons (val1, tem));
- }
- }
-
- return val;
-}
-
-\f
-void
-init_fileio_once ()
-{
- /* Must be set before any path manipulation is performed. */
- XSETFASTINT (Vdirectory_sep_char, '/');