/* Minibuffer input and completion.
- Copyright (C) 1985, 1986, 1993, 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1985, 1986, 93, 94, 95, 1996 Free Software Foundation, Inc.
This file is part of GNU Emacs.
/* Depth in minibuffer invocations. */
int minibuf_level;
-/* Nonzero means display completion help for invalid input */
+/* Nonzero means display completion help for invalid input. */
int auto_help;
+/* The maximum length of a minibuffer history. */
+Lisp_Object Qhistory_length, Vhistory_length;
+
/* Fread_minibuffer leaves the input here as a string. */
Lisp_Object last_minibuf_string;
if (selected_frame != 0
&& !EQ (minibuf_window, selected_frame->minibuffer_window))
{
-#if defined(MSDOS) && !defined(HAVE_X_WINDOWS)
- selected_frame->minibuffer_window = minibuf_window;
-#else
/* I don't think that any frames may validly have a null minibuffer
window anymore. */
if (NILP (selected_frame->minibuffer_window))
Fset_window_buffer (selected_frame->minibuffer_window,
XWINDOW (minibuf_window)->buffer);
minibuf_window = selected_frame->minibuffer_window;
-#endif
}
}
+
+DEFUN ("set-minibuffer-window", Fset_minibuffer_window,
+ Sset_minibuffer_window, 1, 1, 0,
+ "Specify which minibuffer window to use for the minibuffer.\n\
+This effects where the minibuffer is displayed if you put text in it\n\
+without invoking the usual minibuffer commands.")
+ (window)
+ Lisp_Object window;
+{
+ CHECK_WINDOW (window, 1);
+ if (! MINI_WINDOW_P (XWINDOW (window)))
+ error ("Window is not a minibuffer window");
+
+ minibuf_window = window;
+
+ return window;
+}
+
\f
/* Actual minibuffer invocation. */
{
Lisp_Object val;
int count = specpdl_ptr - specpdl;
- Lisp_Object mini_frame;
- struct gcpro gcpro1, gcpro2, gcpro3;
+ Lisp_Object mini_frame, ambient_dir;
+ struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
single_kboard_state ();
val = Qnil;
+ ambient_dir = current_buffer->directory;
+
/* Don't need to protect PROMPT, HISTVAR, and HISTPOS because we
store them away before we can GC. Don't need to protect
BACKUP_N because we use the value only if it is an integer. */
- GCPRO3 (map, initial, val);
+ GCPRO4 (map, initial, val, ambient_dir);
if (!STRINGP (prompt))
prompt = build_string ("");
if (!enable_recursive_minibuffers
- && minibuf_level > 0
- && (EQ (selected_window, minibuf_window)))
- error ("Command attempted to use minibuffer while in minibuffer");
-
- /* Could we simply bind these variables instead? */
- minibuf_save_list
- = Fcons (Voverriding_local_map,
- Fcons (minibuf_window, minibuf_save_list));
- minibuf_save_list
- = Fcons (minibuf_prompt,
- Fcons (make_number (minibuf_prompt_width),
- Fcons (Vhelp_form,
- Fcons (Vcurrent_prefix_arg,
- Fcons (Vminibuffer_history_position,
- Fcons (Vminibuffer_history_variable,
- minibuf_save_list))))));
+ && minibuf_level > 0)
+ {
+ if (EQ (selected_window, minibuf_window))
+ error ("Command attempted to use minibuffer while in minibuffer");
+ else
+ /* If we're in another window, cancel the minibuffer that's active. */
+ Fthrow (Qexit,
+ build_string ("Command attempted to use minibuffer while in minibuffer"));
+ }
- minibuf_prompt_width = 0; /* xdisp.c puts in the right value. */
- minibuf_prompt = Fcopy_sequence (prompt);
- Vminibuffer_history_position = histpos;
- Vminibuffer_history_variable = histvar;
+ /* Choose the minibuffer window and frame, and take action on them. */
choose_minibuf_frame ();
/* If the minibuffer window is on a different frame, save that
frame's configuration too. */
-#ifdef MULTI_FRAME
mini_frame = WINDOW_FRAME (XWINDOW (minibuf_window));
if (XFRAME (mini_frame) != selected_frame)
record_unwind_protect (Fset_window_configuration,
if (minibuffer_auto_raise)
Fraise_frame (mini_frame);
-#endif
- val = current_buffer->directory;
+ /* We have to do this after saving the window configuration
+ since that is what restores the current buffer. */
+
+ /* Arrange to restore a number of minibuffer-related variables.
+ We could bind each variable separately, but that would use lots of
+ specpdl slots. */
+ minibuf_save_list
+ = Fcons (Voverriding_local_map,
+ Fcons (minibuf_window, minibuf_save_list));
+ minibuf_save_list
+ = Fcons (minibuf_prompt,
+ Fcons (make_number (minibuf_prompt_width),
+ Fcons (Vhelp_form,
+ Fcons (Vcurrent_prefix_arg,
+ Fcons (Vminibuffer_history_position,
+ Fcons (Vminibuffer_history_variable,
+ minibuf_save_list))))));
+
+ record_unwind_protect (read_minibuf_unwind, Qnil);
+ minibuf_level++;
+
+ /* Now that we can restore all those variables, start changing them. */
+
+ minibuf_prompt_width = 0; /* xdisp.c puts in the right value. */
+ minibuf_prompt = Fcopy_sequence (prompt);
+ Vminibuffer_history_position = histpos;
+ Vminibuffer_history_variable = histvar;
+ Vhelp_form = Vminibuffer_help_form;
+
+ /* Switch to the minibuffer. */
+
Fset_buffer (get_minibuffer (minibuf_level));
/* The current buffer's default directory is usually the right thing
up Emacs and buf's default directory is Qnil. Here's a hack; can
you think of something better to do? Find another buffer with a
better directory, and use that one instead. */
- if (STRINGP (val))
- current_buffer->directory = val;
+ if (STRINGP (ambient_dir))
+ current_buffer->directory = ambient_dir;
else
{
Lisp_Object buf_list;
}
}
-#ifdef MULTI_FRAME
if (XFRAME (mini_frame) != selected_frame)
Fredirect_frame_focus (Fselected_frame (), mini_frame);
-#endif
- Fmake_local_variable (Qprint_escape_newlines);
- print_escape_newlines = 1;
-
- record_unwind_protect (read_minibuf_unwind, Qnil);
Vminibuf_scroll_window = selected_window;
Fset_window_buffer (minibuf_window, Fcurrent_buffer ());
Fselect_window (minibuf_window);
XSETFASTINT (XWINDOW (minibuf_window)->hscroll, 0);
- Ferase_buffer ();
- minibuf_level++;
+ Fmake_local_variable (Qprint_escape_newlines);
+ print_escape_newlines = 1;
+
+ /* Erase the buffer. */
+ {
+ int count1 = specpdl_ptr - specpdl;
+ specbind (Qinhibit_read_only, Qt);
+ Ferase_buffer ();
+ unbind_to (count1, Qnil);
+ }
+ /* Put in the initial input. */
if (!NILP (initial))
{
Finsert (1, &initial);
/* This is in case the minibuffer-setup-hook calls Fsit_for. */
previous_echo_glyphs = 0;
- Vhelp_form = Vminibuffer_help_form;
current_buffer->keymap = map;
/* Run our hook, but not if it is empty.
(run-hooks would do nothing if it is empty,
- but it's important to save time here in the usual case. */
+ but it's important to save time here in the usual case). */
if (!NILP (Vminibuffer_setup_hook) && !EQ (Vminibuffer_setup_hook, Qunbound)
&& !NILP (Vrun_hooks))
call1 (Vrun_hooks, Qminibuffer_setup_hook);
if (NILP (histval)
|| (CONSP (histval)
&& NILP (Fequal (last_minibuf_string, Fcar (histval)))))
- Fset (Vminibuffer_history_variable,
- Fcons (last_minibuf_string, histval));
+ {
+ Lisp_Object length;
+
+ histval = Fcons (last_minibuf_string, histval);
+ Fset (Vminibuffer_history_variable, histval);
+
+ /* Truncate if requested. */
+ length = Fget (Vminibuffer_history_variable, Qhistory_length);
+ if (NILP (length)) length = Vhistory_length;
+ if (INTEGERP (length)) {
+ if (XINT (length) <= 0)
+ Fset (Vminibuffer_history_variable, Qnil);
+ else
+ {
+ Lisp_Object temp;
+
+ temp = Fnthcdr (Fsub1 (length), histval);
+ if (CONSP (temp)) Fsetcdr (temp, Qnil);
+ }
+ }
+ }
}
/* If Lisp form desired instead of string, parse it. */
Lisp_Object data;
{
Lisp_Object old_deactivate_mark;
+ Lisp_Object window;
/* We are exiting the minibuffer one way or the other,
so run the hook. */
&& !NILP (Vrun_hooks))
safe_run_hooks (Qminibuffer_exit_hook);
- /* Erase the minibuffer we were using at this level. */
- Fset_buffer (XWINDOW (minibuf_window)->buffer);
-
- /* Prevent error in erase-buffer. */
- current_buffer->read_only = Qnil;
-
- old_deactivate_mark = Vdeactivate_mark;
- Ferase_buffer ();
- Vdeactivate_mark = old_deactivate_mark;
-
/* If this was a recursive minibuffer,
- tie the minibuffer window back to the outer level minibuffer buffer */
+ tie the minibuffer window back to the outer level minibuffer buffer. */
minibuf_level--;
- /* Make sure minibuffer window is erased, not ignored */
- windows_or_buffers_changed++;
- XSETFASTINT (XWINDOW (minibuf_window)->last_modified, 0);
- /* Restore prompt, etc from outer minibuffer */
+ window = minibuf_window;
+ /* To keep things predictable, in case it matters, let's be in the minibuffer
+ when we reset the relevant variables. */
+ Fset_buffer (XWINDOW (window)->buffer);
+
+ /* Restore prompt, etc, from outer minibuffer level. */
minibuf_prompt = Fcar (minibuf_save_list);
minibuf_save_list = Fcdr (minibuf_save_list);
minibuf_prompt_width = XFASTINT (Fcar (minibuf_save_list));
minibuf_save_list = Fcdr (minibuf_save_list);
minibuf_window = Fcar (minibuf_save_list);
minibuf_save_list = Fcdr (minibuf_save_list);
+
+ /* Erase the minibuffer we were using at this level. */
+ {
+ int count = specpdl_ptr - specpdl;
+ /* Prevent error in erase-buffer. */
+ specbind (Qinhibit_read_only, Qt);
+ old_deactivate_mark = Vdeactivate_mark;
+ Ferase_buffer ();
+ Vdeactivate_mark = old_deactivate_mark;
+ unbind_to (count, Qnil);
+ }
+
+ /* Make sure minibuffer window is erased, not ignored. */
+ windows_or_buffers_changed++;
+ XSETFASTINT (XWINDOW (window)->last_modified, 0);
+ XSETFASTINT (XWINDOW (window)->last_overlay_modified, 0);
}
\f
If optional second arg INITIAL-CONTENTS is non-nil, it is a string\n\
to be inserted into the minibuffer before reading input.\n\
If INITIAL-CONTENTS is (STRING . POSITION), the initial input\n\
- is STRING, but point is placed POSITION characters into the string.\n\
+ is STRING, but point is placed at position POSITION in the minibuffer.\n\
Third arg KEYMAP is a keymap to use whilst reading;\n\
if omitted or nil, the default is `minibuffer-local-map'.\n\
If fourth arg READ is non-nil, then interpret the result as a lisp object\n\
{
CHECK_NUMBER (position, 0);
/* Convert to distance from end of input. */
- pos = XINT (position) - 1 - XSTRING (initial_contents)->size;
+ if (XINT (position) < 1)
+ /* A number too small means the beginning of the string. */
+ pos = - XSTRING (initial_contents)->size;
+ else
+ pos = XINT (position) - 1 - XSTRING (initial_contents)->size;
}
}
register unsigned char *buffer_string;
int buffer_length, completion_length;
+ CHECK_STRING (completion, 0);
tem = Fbuffer_string ();
GCPRO2 (completion, tem);
/* If reading a file name,
Qminibuffer_exit_hook = intern ("minibuffer-exit-hook");
staticpro (&Qminibuffer_exit_hook);
+ Qhistory_length = intern ("history-length");
+ staticpro (&Qhistory_length);
+
DEFVAR_LISP ("minibuffer-setup-hook", &Vminibuffer_setup_hook,
"Normal hook run just after entry to minibuffer.");
Vminibuffer_setup_hook = Qnil;
"Normal hook run just after exit from minibuffer.");
Vminibuffer_exit_hook = Qnil;
+ DEFVAR_LISP ("history-length", &Vhistory_length,
+ "*Maximum length for history lists before truncation takes place.\n\
+A number means that length; t means infinite. Truncation takes place\n\
+just after a new element is inserted. Setting the history-length\n\
+property of a history variable overrides this default.");
+ XSETFASTINT (Vhistory_length, 30);
+
DEFVAR_BOOL ("completion-auto-help", &auto_help,
"*Non-nil means automatically provide help for invalid completion input.");
auto_help = 1;
"List of regexps that should restrict possible completions.");
Vcompletion_regexp_list = Qnil;
+ defsubr (&Sset_minibuffer_window);
defsubr (&Sread_from_minibuffer);
defsubr (&Seval_minibuffer);
defsubr (&Sread_minibuffer);