/* Minibuffer input and completion.
- Copyright (C) 1985, 1986, 1993, 1994, 1995, 1996, 1997, 1998, 1999
- Free Software Foundation, Inc.
+ Copyright (C) 1985, 1986, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+ 2000, 2001 Free Software Foundation, Inc.
This file is part of GNU Emacs.
#include "buffer.h"
#include "charset.h"
#include "dispextern.h"
+#include "keyboard.h"
#include "frame.h"
#include "window.h"
#include "syntax.h"
-#include "keyboard.h"
+#include "intervals.h"
#define min(a, b) ((a) < (b) ? (a) : (b))
/* Nonzero means display completion help for invalid input. */
-int auto_help;
+Lisp_Object Vcompletion_auto_help;
/* The maximum length of a minibuffer history. */
Lisp_Object Vminibuffer_history_position;
+/* Text properties that are added to minibuffer prompts.
+ These are in addition to the basic `field' property, and stickiness
+ properties. */
+
+Lisp_Object Vminibuffer_prompt_properties;
+
Lisp_Object Qminibuffer_history, Qbuffer_name_history;
Lisp_Object Qread_file_name_internal;
{
int size, len;
char *line, *s;
- struct gcpro gcpro1, gcpro2;
Lisp_Object val;
fprintf (stdout, "%s", XSTRING (prompt)->data);
fflush (stdout);
+ val = Qnil;
size = 100;
len = 0;
line = (char *) xmalloc (size * sizeof *line);
specbind (Qminibuffer_default, defalt);
single_kboard_state ();
+#ifdef HAVE_X_WINDOWS
+ if (display_hourglass_p)
+ cancel_hourglass ();
+#endif
val = Qnil;
ambient_dir = current_buffer->directory;
}
if (noninteractive)
- return read_minibuf_noninteractive (map, initial, prompt, backup_n,
- expflag, histvar, histpos, defalt,
- allow_props, inherit_input_method);
+ {
+ val = read_minibuf_noninteractive (map, initial, prompt, backup_n,
+ expflag, histvar, histpos, defalt,
+ allow_props, inherit_input_method);
+ return unbind_to (count, val);
+ }
/* Choose the minibuffer window and frame, and take action on them. */
/* Erase the buffer. */
{
- int count1 = specpdl_ptr - specpdl;
+ int count1 = BINDING_STACK_SIZE ();
specbind (Qinhibit_read_only, Qt);
+ specbind (Qinhibit_modification_hooks, Qt);
Ferase_buffer ();
unbind_to (count1, Qnil);
}
Qrear_nonsticky, Qt, Qnil);
Fput_text_property (make_number (BEG), make_number (PT),
Qfield, Qt, Qnil);
- Fput_text_property (make_number (BEG), make_number (PT),
- Qread_only, Qt, Qnil);
+ Fadd_text_properties (make_number (BEG), make_number (PT),
+ Vminibuffer_prompt_properties, Qnil);
}
minibuf_prompt_width = current_column ();
&& !NILP (Vrun_hooks))
call1 (Vrun_hooks, Qminibuffer_setup_hook);
+ /* Don't allow the user to undo past this point. */
+ current_buffer->undo_list = Qnil;
+
recursive_edit_1 ();
/* If cursor is on the minibuffer line,
/* Make minibuffer contents into a string. */
Fset_buffer (minibuffer);
- val = Ffield_string (make_number (ZV), allow_props ? Qt : Qnil);
+ if (allow_props)
+ val = Ffield_string (make_number (ZV));
+ else
+ val = Ffield_string_no_properties (make_number (ZV));
/* VAL is the string of minibuffer text. */
Lisp_Object histval;
/* If variable is unbound, make it nil. */
- if (EQ (XSYMBOL (Vminibuffer_history_variable)->value, Qunbound))
+ if (EQ (SYMBOL_VALUE (Vminibuffer_history_variable), Qunbound))
Fset (Vminibuffer_history_variable, Qnil);
histval = Fsymbol_value (Vminibuffer_history_variable);
int count = specpdl_ptr - specpdl;
/* Prevent error in erase-buffer. */
specbind (Qinhibit_read_only, Qt);
+ specbind (Qinhibit_modification_hooks, Qt);
old_deactivate_mark = Vdeactivate_mark;
Ferase_buffer ();
Vdeactivate_mark = old_deactivate_mark;
if (NILP (keymap))
keymap = Vminibuffer_local_map;
else
- keymap = get_keymap (keymap);
+ keymap = get_keymap (keymap, 1, 0);
if (SYMBOLP (hist))
{
it is used to test each possible match.\n\
The match is a candidate only if PREDICATE returns non-nil.\n\
The argument given to PREDICATE is the alist element\n\
-or the symbol from the obarray.")
+or the symbol from the obarray.\n\
+Additionally to this predicate, `completion-regexp-list'\n\
+is used to further constrain the set of candidates.")
(string, alist, predicate)
Lisp_Object string, alist, predicate;
{
Lisp_Object bestmatch, tail, elt, eltstring;
/* Size in bytes of BESTMATCH. */
- int bestmatchsize;
+ int bestmatchsize = 0;
/* These are in bytes, too. */
int compare, matchsize;
int list = CONSP (alist) || NILP (alist);
- int index, obsize;
+ int index = 0, obsize = 0;
int matchcount = 0;
Lisp_Object bucket, zero, end, tem;
struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
if (!list && !VECTORP (alist))
return call3 (alist, string, predicate, Qnil);
- bestmatch = Qnil;
+ bestmatch = bucket = Qnil;
/* If ALIST is not a list, set TAIL just for gc pro. */
tail = alist;
The match is a candidate only if PREDICATE returns non-nil.\n\
The argument given to PREDICATE is the alist element\n\
or the symbol from the obarray.\n\
+Additionally to this predicate, `completion-regexp-list'\n\
+is used to further constrain the set of candidates.\n\
\n\
If the optional fourth argument HIDE-SPACES is non-nil,\n\
strings in ALIST that start with a space\n\
Lisp_Object tail, elt, eltstring;
Lisp_Object allmatches;
int list = CONSP (alist) || NILP (alist);
- int index, obsize;
+ int index = 0, obsize = 0;
Lisp_Object bucket, tem;
struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
{
return call3 (alist, string, predicate, Qt);
}
- allmatches = Qnil;
+ allmatches = bucket = Qnil;
/* If ALIST is not a list, set TAIL just for gc pro. */
tail = alist;
If INITIAL-INPUT is non-nil, insert it in the minibuffer initially.\n\
If it is (STRING . POSITION), the initial input\n\
is STRING, but point is placed POSITION characters into the string.\n\
+ This feature is deprecated--it is best to pass nil for INITIAL.\n\
HIST, if non-nil, specifies a history list\n\
and optionally the initial position in the list.\n\
It can be a symbol, which is the history list variable to use,\n\
int
do_completion ()
{
- Lisp_Object completion, tem;
+ Lisp_Object completion, string, tem;
int completedp;
Lisp_Object last;
struct gcpro gcpro1, gcpro2;
- completion = Ftry_completion (Ffield_string (ZV),
+ completion = Ftry_completion (Ffield_string (make_number (ZV)),
Vminibuffer_completion_table,
Vminibuffer_completion_predicate);
last = last_exact_completion;
return 1;
}
- /* compiler bug */
- tem = Fstring_equal (completion, Ffield_string(ZV));
- completedp = NILP (tem);
- if (completedp)
+ string = Ffield_string (make_number (ZV));
+
+ /* COMPLETEDP should be true if some completion was done, which
+ doesn't include simply changing the case of the entered string.
+ However, for appearance, the string is rewritten if the case
+ changes. */
+ tem = Fcompare_strings (completion, Qnil, Qnil, string, Qnil, Qnil, Qt);
+ completedp = !EQ (tem, Qt);
+
+ tem = Fcompare_strings (completion, Qnil, Qnil, string, Qnil, Qnil, Qnil);
+ if (!EQ (tem, Qt))
+ /* Rewrite the user's input. */
{
Fdelete_field (make_number (ZV)); /* Some completion happened */
Finsert (1, &completion);
+
+ if (! completedp)
+ /* The case of the string changed, but that's all. We're not
+ sure whether this is a unique completion or not, so try again
+ using the real case (this shouldn't recurse again, because
+ the next time try-completion will return either `t' or the
+ exact string). */
+ {
+ UNGCPRO;
+ return do_completion ();
+ }
}
/* It did find a match. Do we match some possibility exactly now? */
- tem = test_completion (Ffield_string(ZV));
+ tem = test_completion (Ffield_string (make_number (ZV)));
if (NILP (tem))
{
/* not an exact match */
UNGCPRO;
if (completedp)
return 5;
- else if (auto_help)
+ else if (!NILP (Vcompletion_auto_help))
Fminibuffer_completion_help ();
else
temp_echo_area_glyphs (" [Next char not unique]");
last_exact_completion = completion;
if (!NILP (last))
{
- tem = Ffield_string (ZV);
+ tem = Ffield_string (make_number (ZV));
if (!NILP (Fequal (tem, last)))
Fminibuffer_completion_help ();
}
struct buffer *obuf = current_buffer;
Fset_buffer (XWINDOW (window)->buffer);
- tem = Fpos_visible_in_window_p (make_number (ZV), window);
+ tem = Fpos_visible_in_window_p (make_number (ZV), window, Qnil);
if (! NILP (tem))
/* If end is in view, scroll up to the beginning. */
Fset_window_start (window, make_number (BEGV), Qnil);
return Qnil;
case 1:
+ if (PT != ZV)
+ Fgoto_char (make_number (ZV));
temp_echo_area_glyphs (" [Sole completion]");
break;
case 3:
+ if (PT != ZV)
+ Fgoto_char (make_number (ZV));
temp_echo_area_glyphs (" [Complete, but not unique]");
break;
}
Lisp_Object val;
/* Allow user to specify null string */
- if (Ffield_beginning (ZV, Qnil) == ZV)
+ if (XINT (Ffield_beginning (make_number (ZV), Qnil)) == ZV)
goto exit;
- if (!NILP (test_completion (Ffield_string (ZV))))
+ if (!NILP (test_completion (Ffield_string (make_number (ZV)))))
goto exit;
/* Call do_completion, but ignore errors. */
return Qnil;
}
exit:
- Fthrow (Qexit, Qnil);
+ return Fthrow (Qexit, Qnil);
/* NOTREACHED */
}
/* We keep calling Fbuffer_string rather than arrange for GC to
hold onto a pointer to one of the strings thus made. */
- completion = Ftry_completion (Ffield_string (ZV),
+ completion = Ftry_completion (Ffield_string (make_number (ZV)),
Vminibuffer_completion_table,
Vminibuffer_completion_predicate);
if (NILP (completion))
return Qnil;
#if 0 /* How the below code used to look, for reference. */
- tem = Ffield_string (ZV);
+ tem = Ffield_string (make_number (ZV));
b = XSTRING (tem)->data;
i = ZV - 1 - XSTRING (completion)->size;
p = XSTRING (completion)->data;
int buffer_nchars, completion_nchars;
CHECK_STRING (completion, 0);
- tem = Ffield_string (ZV);
+ tem = Ffield_string (make_number (ZV));
GCPRO2 (completion, tem);
/* If reading a file name,
expand any $ENVVAR refs in the buffer and in TEM. */
}
#endif /* Rewritten code */
- prompt_end_charpos = Ffield_beginning (make_number (ZV), Qnil);
+ prompt_end_charpos = XINT (Ffield_beginning (make_number (ZV), Qnil));
{
int prompt_end_bytepos;
if (i == XSTRING (completion)->size)
{
GCPRO1 (completion);
- tem = Ftry_completion (concat2 (Ffield_string (ZV), build_string (" ")),
+ tem = Ftry_completion (concat2 (Ffield_string (make_number (ZV)), build_string (" ")),
Vminibuffer_completion_table,
Vminibuffer_completion_predicate);
UNGCPRO;
{
GCPRO1 (completion);
tem =
- Ftry_completion (concat2 (Ffield_string (ZV), build_string ("-")),
+ Ftry_completion (concat2 (Ffield_string (make_number (ZV)), build_string ("-")),
Vminibuffer_completion_table,
Vminibuffer_completion_predicate);
UNGCPRO;
if (i == ZV - prompt_end_charpos)
{
- if (auto_help)
+ if (!NILP (Vcompletion_auto_help))
Fminibuffer_completion_help ();
return Qnil;
}
int length;
Lisp_Object startpos, endpos;
+ startpos = Qnil;
+
elt = Fcar (tail);
/* Compute the length of this element. */
if (CONSP (elt))
Lisp_Object completions;
message ("Making completion list...");
- completions = Fall_completions (Ffield_string (ZV),
+ completions = Fall_completions (Ffield_string (make_number (ZV)),
Vminibuffer_completion_table,
Vminibuffer_completion_predicate,
Qt);
else
bitch_at_user ();
- Fthrow (Qexit, Qnil);
+ return Fthrow (Qexit, Qnil);
}
DEFUN ("exit-minibuffer", Fexit_minibuffer, Sexit_minibuffer, 0, 0, "",
"Terminate this minibuffer argument.")
()
{
- Fthrow (Qexit, Qnil);
+ return Fthrow (Qexit, Qnil);
}
DEFUN ("minibuffer-depth", Fminibuffer_depth, Sminibuffer_depth, 0, 0, 0,
property of a history variable overrides this default.");
XSETFASTINT (Vhistory_length, 30);
- DEFVAR_BOOL ("completion-auto-help", &auto_help,
+ DEFVAR_LISP ("completion-auto-help", &Vcompletion_auto_help,
"*Non-nil means automatically provide help for invalid completion input.");
- auto_help = 1;
+ Vcompletion_auto_help = Qt;
DEFVAR_BOOL ("completion-ignore-case", &completion_ignore_case,
"Non-nil means don't consider case significant in completion.");
with completion; they always discard text properties.");
minibuffer_allow_text_properties = 0;
+ DEFVAR_LISP ("minibuffer-prompt-properties", &Vminibuffer_prompt_properties,
+ "Text properties that are added to minibuffer prompts.\n\
+These are in addition to the basic `field' property, and stickiness\n\
+properties.");
+ /* We use `intern' here instead of Qread_only to avoid
+ initialization-order problems. */
+ Vminibuffer_prompt_properties
+ = Fcons (intern ("read-only"), Fcons (Qt, Qnil));
+
defsubr (&Sset_minibuffer_window);
defsubr (&Sread_from_minibuffer);
defsubr (&Seval_minibuffer);