/* Minibuffer input and completion.
- Copyright (C) 1985, 1986, 93, 94, 95, 1996 Free Software Foundation, Inc.
+ Copyright (C) 1985, 1986, 1993, 1994, 1995, 1996, 1997
+ Free Software Foundation, Inc.
This file is part of GNU Emacs.
Lisp_Object Qminibuffer_setup_hook, Vminibuffer_setup_hook;
Lisp_Object Qminibuffer_exit_hook, Vminibuffer_exit_hook;
+/* Function to call to read a buffer name. */
+Lisp_Object Vread_buffer_function;
+
/* Nonzero means completion ignores case. */
int completion_ignore_case;
\f
/* Actual minibuffer invocation. */
-static void read_minibuf_unwind ();
-Lisp_Object get_minibuffer ();
-static Lisp_Object read_minibuf ();
+static Lisp_Object read_minibuf_unwind P_ ((Lisp_Object));
+static Lisp_Object read_minibuf P_ ((Lisp_Object, Lisp_Object,
+ Lisp_Object, Lisp_Object,
+ int, Lisp_Object,
+ Lisp_Object, Lisp_Object,
+ int, int));
/* Read from the minibuffer using keymap MAP, initial contents INITIAL
- (a string), putting point minus BACKUP_N chars from the end of INITIAL,
+ (a string), putting point minus BACKUP_N bytes from the end of INITIAL,
prompting with PROMPT (a string), using history list HISTVAR
with initial position HISTPOS. (BACKUP_N should be <= 0.)
Lisp_Object histvar;
Lisp_Object histpos;
Lisp_Object defalt;
+ int allow_props;
int inherit_input_method;
{
Lisp_Object val;
int count = specpdl_ptr - specpdl;
Lisp_Object mini_frame, ambient_dir, minibuffer, input_method;
struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
+ Lisp_Object enable_multibyte;
specbind (Qminibuffer_default, defalt);
val = Qnil;
ambient_dir = current_buffer->directory;
input_method = Qnil;
+ enable_multibyte = Qnil;
/* Don't need to protect PROMPT, HISTVAR, and HISTPOS because we
store them away before we can GC. Don't need to protect
Vhelp_form = Vminibuffer_help_form;
if (inherit_input_method)
- /* `current-input-method' is buffer local. So, remeber it in
- INPUT_METHOD before changing the current buffer. */
- input_method = Fsymbol_value (Qcurrent_input_method);
+ {
+ /* `current-input-method' is buffer local. So, remeber it in
+ INPUT_METHOD before changing the current buffer. */
+ input_method = Fsymbol_value (Qcurrent_input_method);
+ enable_multibyte = current_buffer->enable_multibyte_characters;
+ }
/* Switch to the minibuffer. */
if (!NILP (initial))
{
Finsert (1, &initial);
- if (!NILP (backup_n) && INTEGERP (backup_n))
- Fgoto_char (make_number (PT + XFASTINT (backup_n)));
+ if (INTEGERP (backup_n))
+ Fforward_char (backup_n);
}
echo_area_glyphs = 0;
current_buffer->keymap = map;
/* Turn on an input method stored in INPUT_METHOD if any. */
- if (STRINGP (input_method) && Ffboundp (Qactivate_input_method))
+ if (STRINGP (input_method) && !NILP (Ffboundp (Qactivate_input_method)))
call1 (Qactivate_input_method, input_method);
+ /* If appropriate, copy enable-multibyte-characters into the minibuffer. */
+ if (inherit_input_method)
+ current_buffer->enable_multibyte_characters = enable_multibyte;
+
/* 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). */
#endif
/* VAL is the string of minibuffer text. */
+
+ if (STRINGP (val) && XSTRING (val)->size == 0 && ! NILP (defalt))
+ val = defalt;
+
last_minibuf_string = val;
/* Add the value to the appropriate history list unless it is empty. */
{
Lisp_Object expr_and_pos;
unsigned char *p;
+ int pos;
expr_and_pos = Fread_from_string (val, Qnil, Qnil);
- /* Ignore trailing whitespace; any other trailing junk is an error. */
- for (p = XSTRING (val)->data + XINT (Fcdr (expr_and_pos)); *p; p++)
- if (*p != ' ' && *p != '\t' && *p != '\n')
- error ("Trailing garbage following expression");
+ pos = XINT (Fcdr (expr_and_pos));
+ if (pos != XSTRING (val)->size)
+ {
+ /* Ignore trailing whitespace; any other trailing junk is an error. */
+ int i;
+ pos = string_char_to_byte (val, pos);
+ for (i = pos; i < XSTRING (val)->size_byte; i++)
+ {
+ int c = XSTRING (val)->data[i];
+ if (c != ' ' && c != '\t' && c != '\n')
+ error ("Trailing garbage following expression");
+ }
+ }
val = Fcar (expr_and_pos);
}
/* This function is called on exiting minibuffer, whether normally or not,
and it restores the current window, buffer, etc. */
-static void
+static Lisp_Object
read_minibuf_unwind (data)
Lisp_Object data;
{
windows_or_buffers_changed++;
XSETFASTINT (XWINDOW (window)->last_modified, 0);
XSETFASTINT (XWINDOW (window)->last_overlay_modified, 0);
+
+ return Qnil;
}
\f
Sixth arg DEFAULT-VALUE is the default value. If non-nil, it is used\n\
for history commands, and as the value to return if the user enters\n\
the empty string.\n\
-Seventh arg INHERIT-INPUT-METHOD non-nil means the minibuffer inherits\n\
- the current input method.\n\
+Seventh arg INHERIT-INPUT-METHOD, if non-nil, means the minibuffer inherits\n\
+ the current input method and the setting of enable-multibyte-characters.\n\
If the variable `minibuffer-allow-text-properties is non-nil,\n\
then the string which is returned includes whatever text properties\n\
were present in the minibuffer. Otherwise the value has no text properties.")
histvar, histpos, default_value,
minibuffer_allow_text_properties,
!NILP (inherit_input_method));
- if (STRINGP (val) && XSTRING (val)->size == 0 && ! NILP (default_value))
- val = default_value;
UNGCPRO;
return val;
}
The third arg HISTORY, if non-nil, specifies a history list\n\
and optionally the initial position in the list.\n\
See `read-from-minibuffer' for details of HISTORY argument.\n\
-The forth arg INHERIT-INPUT-METHOD non-nil means the minibuffer inherits\n\
- the current input method.")
+Fourth arg INHERIT-INPUT-METHOD, if non-nil, means the minibuffer inherits\n\
+ the current input method and the setting of enable-multibyte-characters.")
(prompt, initial_input, history, default_value, inherit_input_method)
Lisp_Object prompt, initial_input, history, default_value;
Lisp_Object inherit_input_method;
DEFUN ("read-no-blanks-input", Fread_no_blanks_input, Sread_no_blanks_input, 1, 3, 0,
"Args PROMPT and INIT, strings. Read a string from the terminal, not allowing blanks.\n\
Prompt with PROMPT, and provide INIT as an initial value of the input string.\n\
-The third optional arg INHERIT-INPUT-METHOD non-nil means the minibuffer\n\
- inherits the current input method.")
+Third arg INHERIT-INPUT-METHOD, if non-nil, means the minibuffer inherits\n\
+the current input method and the setting of enable-multibyte-characters.")
(prompt, init, inherit_input_method)
Lisp_Object prompt, init, inherit_input_method;
{
(prompt, default_value)
Lisp_Object prompt, default_value;
{
- return Fintern (Fcompleting_read (prompt, Vobarray, Qcommandp, Qt,
- Qnil, Qnil, default_value, Qnil),
- Qnil);
+ Lisp_Object name, default_string;
+
+ if (NILP (default_value))
+ default_string = Qnil;
+ else if (SYMBOLP (default_value))
+ XSETSTRING (default_string, XSYMBOL (default_value)->name);
+ else
+ default_string = default_value;
+
+ name = Fcompleting_read (prompt, Vobarray, Qcommandp, Qt,
+ Qnil, Qnil, default_string, Qnil);
+ if (NILP (name))
+ return name;
+ return Fintern (name, Qnil);
}
#ifdef NOTDEF
(prompt, default_value)
Lisp_Object prompt, default_value;
{
- return Fintern (Fcompleting_read (prompt, Vobarray,
- Quser_variable_p, Qt,
- Qnil, Qnil, default_value, Qnil),
- Qnil);
+ Lisp_Object name, default_string;
+
+ if (NILP (default_value))
+ default_string = Qnil;
+ else if (SYMBOLP (default_value))
+ XSETSTRING (default_string, XSYMBOL (default_value)->name);
+ else
+ default_string = default_value;
+
+ name = Fcompleting_read (prompt, Vobarray,
+ Quser_variable_p, Qt,
+ Qnil, Qnil, default_string, Qnil);
+ if (NILP (name))
+ return name;
+ return Fintern (name, Qnil);
}
DEFUN ("read-buffer", Fread_buffer, Sread_buffer, 1, 3, 0,
Lisp_Object prompt, def, require_match;
{
Lisp_Object tem;
- Lisp_Object args[3];
-
+ Lisp_Object args[4];
+
if (BUFFERP (def))
def = XBUFFER (def)->name;
- if (!NILP (def))
+
+ if (NILP (Vread_buffer_function))
+ {
+ if (!NILP (def))
+ {
+ args[0] = build_string ("%s(default %s) ");
+ args[1] = prompt;
+ args[2] = def;
+ prompt = Fformat (3, args);
+ }
+
+ return Fcompleting_read (prompt, Vbuffer_alist, Qnil,
+ require_match, Qnil, Qnil, def, Qnil);
+ }
+ else
{
- args[0] = build_string ("%s(default %s) ");
+ args[0] = Vread_buffer_function;
args[1] = prompt;
args[2] = def;
- prompt = Fformat (3, args);
+ args[3] = require_match;
+ return Ffuncall(4, args);
}
- return Fcompleting_read (prompt, Vbuffer_alist, Qnil,
- require_match, Qnil, Qnil, def, Qnil);
}
\f
DEFUN ("try-completion", Ftry_completion, Stry_completion, 2, 3, 0,
Lisp_Object string, alist, predicate;
{
Lisp_Object bestmatch, tail, elt, eltstring;
+ /* Size in bytes of BESTMATCH. */
int bestmatchsize;
+ /* These are in bytes, too. */
int compare, matchsize;
int list = CONSP (alist) || NILP (alist);
int index, obsize;
/* Is this element a possible completion? */
if (STRINGP (eltstring)
- && XSTRING (string)->size <= XSTRING (eltstring)->size
+ && XSTRING (string)->size_byte <= XSTRING (eltstring)->size_byte
&& 0 > scmp (XSTRING (eltstring)->data, XSTRING (string)->data,
- XSTRING (string)->size))
+ XSTRING (string)->size_byte))
{
/* Yes. */
Lisp_Object regexps;
matchcount++;
if (NILP (bestmatch))
- bestmatch = eltstring, bestmatchsize = XSTRING (eltstring)->size;
+ {
+ bestmatch = eltstring;
+ bestmatchsize = XSTRING (eltstring)->size_byte;
+ }
else
{
- compare = min (bestmatchsize, XSTRING (eltstring)->size);
+ compare = min (bestmatchsize, XSTRING (eltstring)->size_byte);
matchsize = scmp (XSTRING (bestmatch)->data,
XSTRING (eltstring)->data,
compare);
use it as the best match rather than one that is not an
exact match. This way, we get the case pattern
of the actual match. */
- if ((matchsize == XSTRING (eltstring)->size
- && matchsize < XSTRING (bestmatch)->size)
+ if ((matchsize == XSTRING (eltstring)->size_byte
+ && matchsize < XSTRING (bestmatch)->size_byte)
||
/* If there is more than one exact match ignoring case,
and one of them is exact including case,
/* If there is no exact match ignoring case,
prefer a match that does not change the case
of the input. */
- ((matchsize == XSTRING (eltstring)->size)
+ ((matchsize == XSTRING (eltstring)->size_byte)
==
- (matchsize == XSTRING (bestmatch)->size)
+ (matchsize == XSTRING (bestmatch)->size_byte)
&& !bcmp (XSTRING (eltstring)->data,
- XSTRING (string)->data, XSTRING (string)->size)
+ XSTRING (string)->data,
+ XSTRING (string)->size_byte)
&& bcmp (XSTRING (bestmatch)->data,
- XSTRING (string)->data, XSTRING (string)->size)))
+ XSTRING (string)->data,
+ XSTRING (string)->size_byte)))
bestmatch = eltstring;
}
bestmatchsize = matchsize;
/* If we are ignoring case, and there is no exact match,
and no additional text was supplied,
don't change the case of what the user typed. */
- if (completion_ignore_case && bestmatchsize == XSTRING (string)->size
- && XSTRING (bestmatch)->size > bestmatchsize)
+ if (completion_ignore_case && bestmatchsize == XSTRING (string)->size_byte
+ && XSTRING (bestmatch)->size_byte > bestmatchsize)
return string;
/* Return t if the supplied string is an exact match (counting case);
it does not require any change to be made. */
- if (matchcount == 1 && bestmatchsize == XSTRING (string)->size
+ if (matchcount == 1 && bestmatchsize == XSTRING (string)->size_byte
&& !bcmp (XSTRING (bestmatch)->data, XSTRING (string)->data,
bestmatchsize))
return Qt;
+ bestmatchsize = string_byte_to_char (bestmatch, bestmatchsize);
+
XSETFASTINT (zero, 0); /* Else extract the part in which */
XSETFASTINT (end, bestmatchsize); /* all completions agree */
return Fsubstring (bestmatch, zero, end);
/* Is this element a possible completion? */
if (STRINGP (eltstring)
- && XSTRING (string)->size <= XSTRING (eltstring)->size
+ && XSTRING (string)->size_byte <= XSTRING (eltstring)->size_byte
/* If HIDE_SPACES, reject alternatives that start with space
unless the input starts with space. */
- && ((XSTRING (string)->size > 0 && XSTRING (string)->data[0] == ' ')
+ && ((XSTRING (string)->size_byte > 0
+ && XSTRING (string)->data[0] == ' ')
|| XSTRING (eltstring)->data[0] != ' '
|| NILP (hide_spaces))
&& 0 > scmp (XSTRING (eltstring)->data, XSTRING (string)->data,
- XSTRING (string)->size))
+ XSTRING (string)->size_byte))
{
/* Yes. */
Lisp_Object regexps;
or it can be a cons cell (HISTVAR . HISTPOS).\n\
In that case, HISTVAR is the history list variable to use,\n\
and HISTPOS is the initial position (the position in the list\n\
- which INITIAL-CONTENTS corresponds to).\n\
+ which INITIAL-INPUT corresponds to).\n\
Positions are counted starting from 1 at the beginning of the list.\n\
DEF, if non-nil, is the default value.\n\
\n\
If INHERIT-INPUT-METHOD is non-nil, the minibuffer inherits\n\
- the current input method.\n\
+ the current input method and the setting of enable-multibyte-characters.\n\
\n\
Completion ignores case if the ambient value of\n\
`completion-ignore-case' is non-nil."
init, prompt, make_number (pos), 0,
histvar, histpos, def, 0,
!NILP (inherit_input_method));
- if (STRINGP (val) && XSTRING (val)->size == 0 && ! NILP (def))
- val = def;
RETURN_UNGCPRO (unbind_to (count, val));
}
\f
Lisp_Object Fminibuffer_completion_help ();
Lisp_Object assoc_for_completion ();
-/* A subroutine of Fintern_soft. */
-extern Lisp_Object oblookup ();
-
/* Test whether TXT is an exact completion. */
Lisp_Object
{
/* Bypass intern-soft as that loses for nil */
tem = oblookup (Vminibuffer_completion_table,
- XSTRING (txt)->data, XSTRING (txt)->size);
+ XSTRING (txt)->data,
+ XSTRING (txt)->size,
+ XSTRING (txt)->size_byte);
if (!SYMBOLP (tem))
return Qnil;
else if (!NILP (Vminibuffer_completion_predicate))
()
{
Lisp_Object completion, tem;
- register int i;
+ register int i, i_byte;
register unsigned char *completion_string;
struct gcpro gcpro1, gcpro2;
#else /* Rewritten code */
{
register unsigned char *buffer_string;
- int buffer_length, completion_length;
+ int buffer_nbytes, completion_nbytes;
CHECK_STRING (completion, 0);
tem = Fbuffer_string ();
{
tem = substituted;
Ferase_buffer ();
- insert_from_string (tem, 0, XSTRING (tem)->size, 0);
+ insert_from_string (tem, 0, 0, XSTRING (tem)->size,
+ XSTRING (tem)->size_byte, 0);
}
}
buffer_string = XSTRING (tem)->data;
completion_string = XSTRING (completion)->data;
- buffer_length = XSTRING (tem)->size; /* ie ZV - BEGV */
- completion_length = XSTRING (completion)->size;
- i = buffer_length - completion_length;
- /* Mly: I don't understand what this is supposed to do AT ALL */
+ buffer_nbytes = XSTRING (tem)->size_byte; /* ie ZV_BYTE - BEGV_BYTE */
+ completion_nbytes = XSTRING (completion)->size_byte;
+ i_byte = buffer_nbytes - completion_nbytes;
if (i > 0 ||
- 0 <= scmp (buffer_string, completion_string, buffer_length))
+ 0 <= scmp (buffer_string, completion_string, buffer_nbytes))
{
/* Set buffer to longest match of buffer tail and completion head. */
- if (i <= 0) i = 1;
- buffer_string += i;
- buffer_length -= i;
- while (0 <= scmp (buffer_string++, completion_string, buffer_length--))
- i++;
- del_range (1, i + 1);
- SET_PT (ZV);
+ if (i_byte <= 0) i_byte = 1;
+ buffer_string += i_byte;
+ buffer_nbytes -= i_byte;
+ while (0 <= scmp (buffer_string++, completion_string, buffer_nbytes--))
+ i_byte++;
+ del_range_byte (1, i_byte + 1, 1);
+ SET_PT_BOTH (ZV, ZV_BYTE);
}
UNGCPRO;
}
#endif /* Rewritten code */
+ i_byte = ZV_BYTE - BEGV_BYTE;
i = ZV - BEGV;
/* If completion finds next char not unique,
int len, c;
completion_string = XSTRING (completion)->data;
- for (; i < XSTRING (completion)->size; i += len)
+ for (; i_byte < XSTRING (completion)->size_byte; i_byte += len, i++)
{
- c = STRING_CHAR_AND_LENGTH (completion_string + i,
- XSTRING (completion)->size - i,
+ c = STRING_CHAR_AND_LENGTH (completion_string + i_byte,
+ XSTRING (completion)->size - i_byte,
len);
if (SYNTAX (c) != Sword)
{
- i += len;
+ i_byte += len;
+ i++;
break;
}
}
/* If got no characters, print help for user. */
- if (i == ZV - BEGV)
+ if (i_byte == ZV_BYTE - BEGV_BYTE)
{
if (auto_help)
Fminibuffer_completion_help ();
/* Otherwise insert in minibuffer the chars we got */
Ferase_buffer ();
- insert_from_string (completion, 0, i, 1);
+ insert_from_string (completion, 0, 0, i, i_byte, 1);
return Qt;
}
\f
that has no possible completions, and other quick, unobtrusive
messages. */
+void
temp_echo_area_glyphs (m)
char *m;
{
int osize = ZV;
+ int osize_byte = ZV_BYTE;
int opoint = PT;
+ int opoint_byte = PT_BYTE;
Lisp_Object oinhibit;
oinhibit = Vinhibit_quit;
/* Clear out any old echo-area message to make way for our new thing. */
message (0);
- SET_PT (osize);
+ SET_PT_BOTH (osize, osize_byte);
insert_string (m);
- SET_PT (opoint);
+ SET_PT_BOTH (opoint, opoint_byte);
Vinhibit_quit = Qt;
Fsit_for (make_number (2), Qnil, Qnil);
- del_range (osize, ZV);
- SET_PT (opoint);
+ del_range_both (osize, ZV, osize_byte, ZV_BYTE, 1);
+ SET_PT_BOTH (opoint, opoint_byte);
if (!NILP (Vquit_flag))
{
Vquit_flag = Qnil;
return Qnil;
}
\f
+void
init_minibuf_once ()
{
Vminibuffer_list = Qnil;
staticpro (&Vminibuffer_list);
}
+void
syms_of_minibuf ()
{
minibuf_level = 0;
Qactivate_input_method = intern ("activate-input-method");
staticpro (&Qactivate_input_method);
+ DEFVAR_LISP ("read-buffer-function", &Vread_buffer_function,
+ "If this is non-nil, `read-buffer' does its work by calling this function.");
+ Vread_buffer_function = Qnil;
+
DEFVAR_LISP ("minibuffer-setup-hook", &Vminibuffer_setup_hook,
"Normal hook run just after entry to minibuffer.");
Vminibuffer_setup_hook = Qnil;
DEFVAR_BOOL ("enable-recursive-minibuffers", &enable_recursive_minibuffers,
"*Non-nil means to allow minibuffer commands while in the minibuffer.\n\
-More precisely, this variable makes a difference when the minibuffer window\n\
-is the selected window. If you are in some other window, minibuffer commands\n\
-are allowed even if a minibuffer is active.");
+This variable makes a difference whenever the minibuffer window is active.");
enable_recursive_minibuffers = 0;
DEFVAR_LISP ("minibuffer-completion-table", &Vminibuffer_completion_table,
defsubr (&Sminibuffer_message);
}
+void
keys_of_minibuf ()
{
initial_define_key (Vminibuffer_local_map, Ctl ('g'),