xref: /openbsd-src/gnu/lib/libreadline/complete.c (revision 9704b281e65e1189747652d0ba55eee892cff5f7)
11acd27e7Smillert /* complete.c -- filename completion for readline. */
21acd27e7Smillert 
31acd27e7Smillert /* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.
41acd27e7Smillert 
51acd27e7Smillert    This file is part of the GNU Readline Library, a library for
61acd27e7Smillert    reading lines of text with interactive input and history editing.
71acd27e7Smillert 
81acd27e7Smillert    The GNU Readline Library is free software; you can redistribute it
91acd27e7Smillert    and/or modify it under the terms of the GNU General Public License
101acd27e7Smillert    as published by the Free Software Foundation; either version 2, or
111acd27e7Smillert    (at your option) any later version.
121acd27e7Smillert 
131acd27e7Smillert    The GNU Readline Library is distributed in the hope that it will be
141acd27e7Smillert    useful, but WITHOUT ANY WARRANTY; without even the implied warranty
151acd27e7Smillert    of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
161acd27e7Smillert    GNU General Public License for more details.
171acd27e7Smillert 
181acd27e7Smillert    The GNU General Public License is often shipped with GNU software, and
191acd27e7Smillert    is generally kept in a file called COPYING or LICENSE.  If you do not
201acd27e7Smillert    have a copy of the license, write to the Free Software Foundation,
211acd27e7Smillert    59 Temple Place, Suite 330, Boston, MA 02111 USA. */
221acd27e7Smillert #define READLINE_LIBRARY
231acd27e7Smillert 
241acd27e7Smillert #if defined (HAVE_CONFIG_H)
251acd27e7Smillert #  include <config.h>
261acd27e7Smillert #endif
271acd27e7Smillert 
281acd27e7Smillert #include <sys/types.h>
291acd27e7Smillert #include <fcntl.h>
301acd27e7Smillert #if defined (HAVE_SYS_FILE_H)
311acd27e7Smillert #include <sys/file.h>
321acd27e7Smillert #endif
331acd27e7Smillert 
341acd27e7Smillert #if defined (HAVE_UNISTD_H)
351acd27e7Smillert #  include <unistd.h>
361acd27e7Smillert #endif /* HAVE_UNISTD_H */
371acd27e7Smillert 
381acd27e7Smillert #if defined (HAVE_STDLIB_H)
391acd27e7Smillert #  include <stdlib.h>
401acd27e7Smillert #else
411acd27e7Smillert #  include "ansi_stdlib.h"
421acd27e7Smillert #endif /* HAVE_STDLIB_H */
431acd27e7Smillert 
441acd27e7Smillert #include <stdio.h>
451acd27e7Smillert 
461acd27e7Smillert #include <errno.h>
471acd27e7Smillert #if !defined (errno)
481acd27e7Smillert extern int errno;
491acd27e7Smillert #endif /* !errno */
501acd27e7Smillert 
511acd27e7Smillert #include <pwd.h>
521acd27e7Smillert 
531acd27e7Smillert #include "posixdir.h"
541acd27e7Smillert #include "posixstat.h"
551acd27e7Smillert 
561acd27e7Smillert /* System-specific feature definitions and include files. */
571acd27e7Smillert #include "rldefs.h"
58af70c2dfSkettenis #include "rlmbutil.h"
591acd27e7Smillert 
601acd27e7Smillert /* Some standard library routines. */
611acd27e7Smillert #include "readline.h"
621acd27e7Smillert #include "xmalloc.h"
631acd27e7Smillert #include "rlprivate.h"
641acd27e7Smillert 
651acd27e7Smillert #ifdef __STDC__
661acd27e7Smillert typedef int QSFUNC (const void *, const void *);
671acd27e7Smillert #else
681acd27e7Smillert typedef int QSFUNC ();
691acd27e7Smillert #endif
701acd27e7Smillert 
71af70c2dfSkettenis #ifdef HAVE_LSTAT
72af70c2dfSkettenis #  define LSTAT lstat
73af70c2dfSkettenis #else
74af70c2dfSkettenis #  define LSTAT stat
75af70c2dfSkettenis #endif
76af70c2dfSkettenis 
77af70c2dfSkettenis /* Unix version of a hidden file.  Could be different on other systems. */
78af70c2dfSkettenis #define HIDDEN_FILE(fname)	((fname)[0] == '.')
79af70c2dfSkettenis 
80af70c2dfSkettenis /* Most systems don't declare getpwent in <pwd.h> if _POSIX_SOURCE is
81af70c2dfSkettenis    defined. */
82af70c2dfSkettenis #if !defined (HAVE_GETPW_DECLS) || defined (_POSIX_SOURCE)
83af70c2dfSkettenis extern struct passwd *getpwent PARAMS((void));
84af70c2dfSkettenis #endif /* !HAVE_GETPW_DECLS || _POSIX_SOURCE */
85af70c2dfSkettenis 
861acd27e7Smillert /* If non-zero, then this is the address of a function to call when
871acd27e7Smillert    completing a word would normally display the list of possible matches.
881acd27e7Smillert    This function is called instead of actually doing the display.
891acd27e7Smillert    It takes three arguments: (char **matches, int num_matches, int max_length)
901acd27e7Smillert    where MATCHES is the array of strings that matched, NUM_MATCHES is the
911acd27e7Smillert    number of strings in that array, and MAX_LENGTH is the length of the
921acd27e7Smillert    longest string in that array. */
93af70c2dfSkettenis rl_compdisp_func_t *rl_completion_display_matches_hook = (rl_compdisp_func_t *)NULL;
941acd27e7Smillert 
951acd27e7Smillert #if defined (VISIBLE_STATS)
961acd27e7Smillert #  if !defined (X_OK)
971acd27e7Smillert #    define X_OK 1
981acd27e7Smillert #  endif
99af70c2dfSkettenis static int stat_char PARAMS((char *));
1001acd27e7Smillert #endif
1011acd27e7Smillert 
102af70c2dfSkettenis static char *rl_quote_filename PARAMS((char *, int, char *));
1031acd27e7Smillert 
104af70c2dfSkettenis static void set_completion_defaults PARAMS((int));
105af70c2dfSkettenis static int get_y_or_n PARAMS((int));
106af70c2dfSkettenis static int _rl_internal_pager PARAMS((int));
107af70c2dfSkettenis static char *printable_part PARAMS((char *));
108af70c2dfSkettenis static int print_filename PARAMS((char *, char *));
109af70c2dfSkettenis 
110af70c2dfSkettenis static char **gen_completion_matches PARAMS((char *, int, int, rl_compentry_func_t *, int, int));
111af70c2dfSkettenis 
112af70c2dfSkettenis static char **remove_duplicate_matches PARAMS((char **));
113af70c2dfSkettenis static void insert_match PARAMS((char *, int, int, char *));
114af70c2dfSkettenis static int append_to_match PARAMS((char *, int, int, int));
115af70c2dfSkettenis static void insert_all_matches PARAMS((char **, int, char *));
116af70c2dfSkettenis static void display_matches PARAMS((char **));
117af70c2dfSkettenis static int compute_lcd_of_matches PARAMS((char **, int, const char *));
118af70c2dfSkettenis static int postprocess_matches PARAMS((char ***, int));
119af70c2dfSkettenis 
120af70c2dfSkettenis static char *make_quoted_replacement PARAMS((char *, int, char *));
1211acd27e7Smillert 
1221acd27e7Smillert /* **************************************************************** */
1231acd27e7Smillert /*								    */
1241acd27e7Smillert /*	Completion matching, from readline's point of view.	    */
1251acd27e7Smillert /*								    */
1261acd27e7Smillert /* **************************************************************** */
1271acd27e7Smillert 
1281acd27e7Smillert /* Variables known only to the readline library. */
1291acd27e7Smillert 
1301acd27e7Smillert /* If non-zero, non-unique completions always show the list of matches. */
1311acd27e7Smillert int _rl_complete_show_all = 0;
1321acd27e7Smillert 
1331acd27e7Smillert /* If non-zero, completed directory names have a slash appended. */
1341acd27e7Smillert int _rl_complete_mark_directories = 1;
1351acd27e7Smillert 
136af70c2dfSkettenis /* If non-zero, the symlinked directory completion behavior introduced in
137af70c2dfSkettenis    readline-4.2a is disabled, and symlinks that point to directories have
138af70c2dfSkettenis    a slash appended (subject to the value of _rl_complete_mark_directories).
139af70c2dfSkettenis    This is user-settable via the mark-symlinked-directories variable. */
140af70c2dfSkettenis int _rl_complete_mark_symlink_dirs = 0;
141af70c2dfSkettenis 
1421acd27e7Smillert /* If non-zero, completions are printed horizontally in alphabetical order,
1431acd27e7Smillert    like `ls -x'. */
1441acd27e7Smillert int _rl_print_completions_horizontally;
1451acd27e7Smillert 
1461acd27e7Smillert /* Non-zero means that case is not significant in filename completion. */
1471acd27e7Smillert #if defined (__MSDOS__) && !defined (__DJGPP__)
1481acd27e7Smillert int _rl_completion_case_fold = 1;
1491acd27e7Smillert #else
1501acd27e7Smillert int _rl_completion_case_fold;
1511acd27e7Smillert #endif
1521acd27e7Smillert 
153af70c2dfSkettenis /* If non-zero, don't match hidden files (filenames beginning with a `.' on
154af70c2dfSkettenis    Unix) when doing filename completion. */
155af70c2dfSkettenis int _rl_match_hidden_files = 1;
156af70c2dfSkettenis 
1571acd27e7Smillert /* Global variables available to applications using readline. */
1581acd27e7Smillert 
1591acd27e7Smillert #if defined (VISIBLE_STATS)
1601acd27e7Smillert /* Non-zero means add an additional character to each filename displayed
1611acd27e7Smillert    during listing completion iff rl_filename_completion_desired which helps
1621acd27e7Smillert    to indicate the type of file being listed. */
1631acd27e7Smillert int rl_visible_stats = 0;
1641acd27e7Smillert #endif /* VISIBLE_STATS */
1651acd27e7Smillert 
1661acd27e7Smillert /* If non-zero, then this is the address of a function to call when
1671acd27e7Smillert    completing on a directory name.  The function is called with
1681acd27e7Smillert    the address of a string (the current directory name) as an arg. */
169af70c2dfSkettenis rl_icppfunc_t *rl_directory_completion_hook = (rl_icppfunc_t *)NULL;
170af70c2dfSkettenis 
171af70c2dfSkettenis rl_icppfunc_t *rl_directory_rewrite_hook = (rl_icppfunc_t *)NULL;
1721acd27e7Smillert 
1731acd27e7Smillert /* Non-zero means readline completion functions perform tilde expansion. */
1741acd27e7Smillert int rl_complete_with_tilde_expansion = 0;
1751acd27e7Smillert 
1761acd27e7Smillert /* Pointer to the generator function for completion_matches ().
177af70c2dfSkettenis    NULL means to use rl_filename_completion_function (), the default filename
1781acd27e7Smillert    completer. */
179af70c2dfSkettenis rl_compentry_func_t *rl_completion_entry_function = (rl_compentry_func_t *)NULL;
1801acd27e7Smillert 
1811acd27e7Smillert /* Pointer to alternative function to create matches.
1821acd27e7Smillert    Function is called with TEXT, START, and END.
1831acd27e7Smillert    START and END are indices in RL_LINE_BUFFER saying what the boundaries
1841acd27e7Smillert    of TEXT are.
1851acd27e7Smillert    If this function exists and returns NULL then call the value of
1861acd27e7Smillert    rl_completion_entry_function to try to match, otherwise use the
1871acd27e7Smillert    array of strings returned. */
188af70c2dfSkettenis rl_completion_func_t *rl_attempted_completion_function = (rl_completion_func_t *)NULL;
1891acd27e7Smillert 
1901acd27e7Smillert /* Non-zero means to suppress normal filename completion after the
1911acd27e7Smillert    user-specified completion function has been called. */
1921acd27e7Smillert int rl_attempted_completion_over = 0;
1931acd27e7Smillert 
1941acd27e7Smillert /* Set to a character indicating the type of completion being performed
1951acd27e7Smillert    by rl_complete_internal, available for use by application completion
1961acd27e7Smillert    functions. */
1971acd27e7Smillert int rl_completion_type = 0;
1981acd27e7Smillert 
1991acd27e7Smillert /* Up to this many items will be displayed in response to a
2001acd27e7Smillert    possible-completions call.  After that, we ask the user if
2011acd27e7Smillert    she is sure she wants to see them all. */
2021acd27e7Smillert int rl_completion_query_items = 100;
2031acd27e7Smillert 
204af70c2dfSkettenis int _rl_page_completions = 1;
205af70c2dfSkettenis 
2061acd27e7Smillert /* The basic list of characters that signal a break between words for the
2071acd27e7Smillert    completer routine.  The contents of this variable is what breaks words
2081acd27e7Smillert    in the shell, i.e. " \t\n\"\\'`@$><=" */
209af70c2dfSkettenis const char *rl_basic_word_break_characters = " \t\n\"\\'`@$><=;|&{("; /* }) */
2101acd27e7Smillert 
2111acd27e7Smillert /* List of basic quoting characters. */
212af70c2dfSkettenis const char *rl_basic_quote_characters = "\"'";
2131acd27e7Smillert 
2141acd27e7Smillert /* The list of characters that signal a break between words for
2151acd27e7Smillert    rl_complete_internal.  The default list is the contents of
2161acd27e7Smillert    rl_basic_word_break_characters.  */
217af70c2dfSkettenis const char *rl_completer_word_break_characters = (const char *)NULL;
2181acd27e7Smillert 
2191acd27e7Smillert /* List of characters which can be used to quote a substring of the line.
2201acd27e7Smillert    Completion occurs on the entire substring, and within the substring
2211acd27e7Smillert    rl_completer_word_break_characters are treated as any other character,
2221acd27e7Smillert    unless they also appear within this list. */
223af70c2dfSkettenis const char *rl_completer_quote_characters = (const char *)NULL;
2241acd27e7Smillert 
2251acd27e7Smillert /* List of characters that should be quoted in filenames by the completer. */
226af70c2dfSkettenis const char *rl_filename_quote_characters = (const char *)NULL;
2271acd27e7Smillert 
2281acd27e7Smillert /* List of characters that are word break characters, but should be left
2291acd27e7Smillert    in TEXT when it is passed to the completion function.  The shell uses
2301acd27e7Smillert    this to help determine what kind of completing to do. */
231af70c2dfSkettenis const char *rl_special_prefixes = (const char *)NULL;
2321acd27e7Smillert 
2331acd27e7Smillert /* If non-zero, then disallow duplicates in the matches. */
2341acd27e7Smillert int rl_ignore_completion_duplicates = 1;
2351acd27e7Smillert 
2361acd27e7Smillert /* Non-zero means that the results of the matches are to be treated
2371acd27e7Smillert    as filenames.  This is ALWAYS zero on entry, and can only be changed
2381acd27e7Smillert    within a completion entry finder function. */
2391acd27e7Smillert int rl_filename_completion_desired = 0;
2401acd27e7Smillert 
2411acd27e7Smillert /* Non-zero means that the results of the matches are to be quoted using
2421acd27e7Smillert    double quotes (or an application-specific quoting mechanism) if the
2431acd27e7Smillert    filename contains any characters in rl_filename_quote_chars.  This is
2441acd27e7Smillert    ALWAYS non-zero on entry, and can only be changed within a completion
2451acd27e7Smillert    entry finder function. */
2461acd27e7Smillert int rl_filename_quoting_desired = 1;
2471acd27e7Smillert 
2481acd27e7Smillert /* This function, if defined, is called by the completer when real
2491acd27e7Smillert    filename completion is done, after all the matching names have been
2501acd27e7Smillert    generated. It is passed a (char**) known as matches in the code below.
2511acd27e7Smillert    It consists of a NULL-terminated array of pointers to potential
2521acd27e7Smillert    matching strings.  The 1st element (matches[0]) is the maximal
2531acd27e7Smillert    substring that is common to all matches. This function can re-arrange
2541acd27e7Smillert    the list of matches as required, but all elements of the array must be
2551acd27e7Smillert    free()'d if they are deleted. The main intent of this function is
2561acd27e7Smillert    to implement FIGNORE a la SunOS csh. */
257af70c2dfSkettenis rl_compignore_func_t *rl_ignore_some_completions_function = (rl_compignore_func_t *)NULL;
2581acd27e7Smillert 
2591acd27e7Smillert /* Set to a function to quote a filename in an application-specific fashion.
2601acd27e7Smillert    Called with the text to quote, the type of match found (single or multiple)
2611acd27e7Smillert    and a pointer to the quoting character to be used, which the function can
2621acd27e7Smillert    reset if desired. */
263af70c2dfSkettenis rl_quote_func_t *rl_filename_quoting_function = rl_quote_filename;
2641acd27e7Smillert 
2651acd27e7Smillert /* Function to call to remove quoting characters from a filename.  Called
2661acd27e7Smillert    before completion is attempted, so the embedded quotes do not interfere
2671acd27e7Smillert    with matching names in the file system.  Readline doesn't do anything
2681acd27e7Smillert    with this; it's set only by applications. */
269af70c2dfSkettenis rl_dequote_func_t *rl_filename_dequoting_function = (rl_dequote_func_t *)NULL;
2701acd27e7Smillert 
2711acd27e7Smillert /* Function to call to decide whether or not a word break character is
2721acd27e7Smillert    quoted.  If a character is quoted, it does not break words for the
2731acd27e7Smillert    completer. */
274af70c2dfSkettenis rl_linebuf_func_t *rl_char_is_quoted_p = (rl_linebuf_func_t *)NULL;
275af70c2dfSkettenis 
276af70c2dfSkettenis /* If non-zero, the completion functions don't append anything except a
277af70c2dfSkettenis    possible closing quote.  This is set to 0 by rl_complete_internal and
278af70c2dfSkettenis    may be changed by an application-specific completion function. */
279af70c2dfSkettenis int rl_completion_suppress_append = 0;
2801acd27e7Smillert 
2811acd27e7Smillert /* Character appended to completed words when at the end of the line.  The
2821acd27e7Smillert    default is a space. */
2831acd27e7Smillert int rl_completion_append_character = ' ';
2841acd27e7Smillert 
285af70c2dfSkettenis /* If non-zero, a slash will be appended to completed filenames that are
286af70c2dfSkettenis    symbolic links to directory names, subject to the value of the
287af70c2dfSkettenis    mark-directories variable (which is user-settable).  This exists so
288af70c2dfSkettenis    that application completion functions can override the user's preference
289af70c2dfSkettenis    (set via the mark-symlinked-directories variable) if appropriate.
290af70c2dfSkettenis    It's set to the value of _rl_complete_mark_symlink_dirs in
291af70c2dfSkettenis    rl_complete_internal before any application-specific completion
292af70c2dfSkettenis    function is called, so without that function doing anything, the user's
293af70c2dfSkettenis    preferences are honored. */
294af70c2dfSkettenis int rl_completion_mark_symlink_dirs;
295af70c2dfSkettenis 
2961acd27e7Smillert /* If non-zero, inhibit completion (temporarily). */
2971acd27e7Smillert int rl_inhibit_completion;
2981acd27e7Smillert 
2991acd27e7Smillert /* Variables local to this file. */
3001acd27e7Smillert 
3011acd27e7Smillert /* Local variable states what happened during the last completion attempt. */
3021acd27e7Smillert static int completion_changed_buffer;
3031acd27e7Smillert 
3041acd27e7Smillert /*************************************/
3051acd27e7Smillert /*				     */
3061acd27e7Smillert /*    Bindable completion functions  */
3071acd27e7Smillert /*				     */
3081acd27e7Smillert /*************************************/
3091acd27e7Smillert 
3101acd27e7Smillert /* Complete the word at or before point.  You have supplied the function
3111acd27e7Smillert    that does the initial simple matching selection algorithm (see
312af70c2dfSkettenis    rl_completion_matches ()).  The default is to do filename completion. */
3131acd27e7Smillert int
rl_complete(ignore,invoking_key)3141acd27e7Smillert rl_complete (ignore, invoking_key)
3151acd27e7Smillert      int ignore, invoking_key;
3161acd27e7Smillert {
3171acd27e7Smillert   if (rl_inhibit_completion)
318af70c2dfSkettenis     return (_rl_insert_char (ignore, invoking_key));
3191acd27e7Smillert   else if (rl_last_func == rl_complete && !completion_changed_buffer)
3201acd27e7Smillert     return (rl_complete_internal ('?'));
3211acd27e7Smillert   else if (_rl_complete_show_all)
3221acd27e7Smillert     return (rl_complete_internal ('!'));
3231acd27e7Smillert   else
3241acd27e7Smillert     return (rl_complete_internal (TAB));
3251acd27e7Smillert }
3261acd27e7Smillert 
3271acd27e7Smillert /* List the possible completions.  See description of rl_complete (). */
3281acd27e7Smillert int
rl_possible_completions(ignore,invoking_key)3291acd27e7Smillert rl_possible_completions (ignore, invoking_key)
3301acd27e7Smillert      int ignore, invoking_key;
3311acd27e7Smillert {
3321acd27e7Smillert   return (rl_complete_internal ('?'));
3331acd27e7Smillert }
3341acd27e7Smillert 
3351acd27e7Smillert int
rl_insert_completions(ignore,invoking_key)3361acd27e7Smillert rl_insert_completions (ignore, invoking_key)
3371acd27e7Smillert      int ignore, invoking_key;
3381acd27e7Smillert {
3391acd27e7Smillert   return (rl_complete_internal ('*'));
3401acd27e7Smillert }
3411acd27e7Smillert 
342af70c2dfSkettenis /* Return the correct value to pass to rl_complete_internal performing
343af70c2dfSkettenis    the same tests as rl_complete.  This allows consecutive calls to an
344af70c2dfSkettenis    application's completion function to list possible completions and for
345af70c2dfSkettenis    an application-specific completion function to honor the
346af70c2dfSkettenis    show-all-if-ambiguous readline variable. */
347af70c2dfSkettenis int
rl_completion_mode(cfunc)348af70c2dfSkettenis rl_completion_mode (cfunc)
349af70c2dfSkettenis      rl_command_func_t *cfunc;
350af70c2dfSkettenis {
351af70c2dfSkettenis   if (rl_last_func == cfunc && !completion_changed_buffer)
352af70c2dfSkettenis     return '?';
353af70c2dfSkettenis   else if (_rl_complete_show_all)
354af70c2dfSkettenis     return '!';
355af70c2dfSkettenis   else
356af70c2dfSkettenis     return TAB;
357af70c2dfSkettenis }
358af70c2dfSkettenis 
3591acd27e7Smillert /************************************/
3601acd27e7Smillert /*				    */
3611acd27e7Smillert /*    Completion utility functions  */
3621acd27e7Smillert /*				    */
3631acd27e7Smillert /************************************/
3641acd27e7Smillert 
365af70c2dfSkettenis /* Set default values for readline word completion.  These are the variables
366af70c2dfSkettenis    that application completion functions can change or inspect. */
367af70c2dfSkettenis static void
set_completion_defaults(what_to_do)368af70c2dfSkettenis set_completion_defaults (what_to_do)
369af70c2dfSkettenis      int what_to_do;
3701acd27e7Smillert {
371af70c2dfSkettenis   /* Only the completion entry function can change these. */
372af70c2dfSkettenis   rl_filename_completion_desired = 0;
373af70c2dfSkettenis   rl_filename_quoting_desired = 1;
374af70c2dfSkettenis   rl_completion_type = what_to_do;
375af70c2dfSkettenis   rl_completion_suppress_append = 0;
3761acd27e7Smillert 
377af70c2dfSkettenis   /* The completion entry function may optionally change this. */
378af70c2dfSkettenis   rl_completion_mark_symlink_dirs = _rl_complete_mark_symlink_dirs;
3791acd27e7Smillert }
3801acd27e7Smillert 
3811acd27e7Smillert /* The user must press "y" or "n". Non-zero return means "y" pressed. */
3821acd27e7Smillert static int
get_y_or_n(for_pager)383af70c2dfSkettenis get_y_or_n (for_pager)
384af70c2dfSkettenis      int for_pager;
3851acd27e7Smillert {
3861acd27e7Smillert   int c;
3871acd27e7Smillert 
3881acd27e7Smillert   for (;;)
3891acd27e7Smillert     {
390af70c2dfSkettenis       RL_SETSTATE(RL_STATE_MOREINPUT);
3911acd27e7Smillert       c = rl_read_key ();
392af70c2dfSkettenis       RL_UNSETSTATE(RL_STATE_MOREINPUT);
393af70c2dfSkettenis 
3941acd27e7Smillert       if (c == 'y' || c == 'Y' || c == ' ')
3951acd27e7Smillert 	return (1);
3961acd27e7Smillert       if (c == 'n' || c == 'N' || c == RUBOUT)
3971acd27e7Smillert 	return (0);
3981acd27e7Smillert       if (c == ABORT_CHAR)
3991acd27e7Smillert 	_rl_abort_internal ();
400af70c2dfSkettenis       if (for_pager && (c == NEWLINE || c == RETURN))
401af70c2dfSkettenis 	return (2);
402af70c2dfSkettenis       if (for_pager && (c == 'q' || c == 'Q'))
403af70c2dfSkettenis 	return (0);
404af70c2dfSkettenis       rl_ding ();
4051acd27e7Smillert     }
4061acd27e7Smillert }
4071acd27e7Smillert 
408af70c2dfSkettenis static int
_rl_internal_pager(lines)409af70c2dfSkettenis _rl_internal_pager (lines)
410af70c2dfSkettenis      int lines;
411af70c2dfSkettenis {
412af70c2dfSkettenis   int i;
413af70c2dfSkettenis 
414af70c2dfSkettenis   fprintf (rl_outstream, "--More--");
415af70c2dfSkettenis   fflush (rl_outstream);
416af70c2dfSkettenis   i = get_y_or_n (1);
417af70c2dfSkettenis   _rl_erase_entire_line ();
418af70c2dfSkettenis   if (i == 0)
419af70c2dfSkettenis     return -1;
420af70c2dfSkettenis   else if (i == 2)
421af70c2dfSkettenis     return (lines - 1);
422af70c2dfSkettenis   else
423af70c2dfSkettenis     return 0;
424af70c2dfSkettenis }
425af70c2dfSkettenis 
4261acd27e7Smillert #if defined (VISIBLE_STATS)
4271acd27e7Smillert /* Return the character which best describes FILENAME.
4281acd27e7Smillert      `@' for symbolic links
4291acd27e7Smillert      `/' for directories
4301acd27e7Smillert      `*' for executables
4311acd27e7Smillert      `=' for sockets
4321acd27e7Smillert      `|' for FIFOs
4331acd27e7Smillert      `%' for character special devices
4341acd27e7Smillert      `#' for block special devices */
4351acd27e7Smillert static int
stat_char(filename)4361acd27e7Smillert stat_char (filename)
4371acd27e7Smillert      char *filename;
4381acd27e7Smillert {
4391acd27e7Smillert   struct stat finfo;
4401acd27e7Smillert   int character, r;
4411acd27e7Smillert 
4421acd27e7Smillert #if defined (HAVE_LSTAT) && defined (S_ISLNK)
4431acd27e7Smillert   r = lstat (filename, &finfo);
4441acd27e7Smillert #else
4451acd27e7Smillert   r = stat (filename, &finfo);
4461acd27e7Smillert #endif
4471acd27e7Smillert 
4481acd27e7Smillert   if (r == -1)
4491acd27e7Smillert     return (0);
4501acd27e7Smillert 
4511acd27e7Smillert   character = 0;
4521acd27e7Smillert   if (S_ISDIR (finfo.st_mode))
4531acd27e7Smillert     character = '/';
4541acd27e7Smillert #if defined (S_ISCHR)
4551acd27e7Smillert   else if (S_ISCHR (finfo.st_mode))
4561acd27e7Smillert     character = '%';
4571acd27e7Smillert #endif /* S_ISCHR */
4581acd27e7Smillert #if defined (S_ISBLK)
4591acd27e7Smillert   else if (S_ISBLK (finfo.st_mode))
4601acd27e7Smillert     character = '#';
4611acd27e7Smillert #endif /* S_ISBLK */
4621acd27e7Smillert #if defined (S_ISLNK)
4631acd27e7Smillert   else if (S_ISLNK (finfo.st_mode))
4641acd27e7Smillert     character = '@';
4651acd27e7Smillert #endif /* S_ISLNK */
4661acd27e7Smillert #if defined (S_ISSOCK)
4671acd27e7Smillert   else if (S_ISSOCK (finfo.st_mode))
4681acd27e7Smillert     character = '=';
4691acd27e7Smillert #endif /* S_ISSOCK */
4701acd27e7Smillert #if defined (S_ISFIFO)
4711acd27e7Smillert   else if (S_ISFIFO (finfo.st_mode))
4721acd27e7Smillert     character = '|';
4731acd27e7Smillert #endif
4741acd27e7Smillert   else if (S_ISREG (finfo.st_mode))
4751acd27e7Smillert     {
4761acd27e7Smillert       if (access (filename, X_OK) == 0)
4771acd27e7Smillert 	character = '*';
4781acd27e7Smillert     }
4791acd27e7Smillert   return (character);
4801acd27e7Smillert }
4811acd27e7Smillert #endif /* VISIBLE_STATS */
4821acd27e7Smillert 
4831acd27e7Smillert /* Return the portion of PATHNAME that should be output when listing
4841acd27e7Smillert    possible completions.  If we are hacking filename completion, we
4851acd27e7Smillert    are only interested in the basename, the portion following the
486af70c2dfSkettenis    final slash.  Otherwise, we return what we were passed.  Since
487af70c2dfSkettenis    printing empty strings is not very informative, if we're doing
488af70c2dfSkettenis    filename completion, and the basename is the empty string, we look
489af70c2dfSkettenis    for the previous slash and return the portion following that.  If
490af70c2dfSkettenis    there's no previous slash, we just return what we were passed. */
4911acd27e7Smillert static char *
printable_part(pathname)4921acd27e7Smillert printable_part (pathname)
4931acd27e7Smillert       char *pathname;
4941acd27e7Smillert {
495af70c2dfSkettenis   char *temp, *x;
4961acd27e7Smillert 
497af70c2dfSkettenis   if (rl_filename_completion_desired == 0)	/* don't need to do anything */
498af70c2dfSkettenis     return (pathname);
499af70c2dfSkettenis 
500af70c2dfSkettenis   temp = strrchr (pathname, '/');
5011acd27e7Smillert #if defined (__MSDOS__)
502af70c2dfSkettenis   if (temp == 0 && ISALPHA ((unsigned char)pathname[0]) && pathname[1] == ':')
5031acd27e7Smillert     temp = pathname + 1;
5041acd27e7Smillert #endif
505af70c2dfSkettenis 
506af70c2dfSkettenis   if (temp == 0 || *temp == '\0')
507af70c2dfSkettenis     return (pathname);
508af70c2dfSkettenis   /* If the basename is NULL, we might have a pathname like '/usr/src/'.
509af70c2dfSkettenis      Look for a previous slash and, if one is found, return the portion
510af70c2dfSkettenis      following that slash.  If there's no previous slash, just return the
511af70c2dfSkettenis      pathname we were passed. */
512af70c2dfSkettenis   else if (temp[1] == '\0')
513af70c2dfSkettenis     {
514af70c2dfSkettenis       for (x = temp - 1; x > pathname; x--)
515af70c2dfSkettenis         if (*x == '/')
516af70c2dfSkettenis           break;
517af70c2dfSkettenis       return ((*x == '/') ? x + 1 : pathname);
518af70c2dfSkettenis     }
519af70c2dfSkettenis   else
520af70c2dfSkettenis     return ++temp;
5211acd27e7Smillert }
5221acd27e7Smillert 
5231acd27e7Smillert /* Output TO_PRINT to rl_outstream.  If VISIBLE_STATS is defined and we
5241acd27e7Smillert    are using it, check for and output a single character for `special'
5251acd27e7Smillert    filenames.  Return the number of characters we output. */
5261acd27e7Smillert 
5271acd27e7Smillert #define PUTX(c) \
5281acd27e7Smillert     do { \
5291acd27e7Smillert       if (CTRL_CHAR (c)) \
5301acd27e7Smillert         { \
5311acd27e7Smillert           putc ('^', rl_outstream); \
5321acd27e7Smillert           putc (UNCTRL (c), rl_outstream); \
5331acd27e7Smillert           printed_len += 2; \
5341acd27e7Smillert         } \
5351acd27e7Smillert       else if (c == RUBOUT) \
5361acd27e7Smillert 	{ \
5371acd27e7Smillert 	  putc ('^', rl_outstream); \
5381acd27e7Smillert 	  putc ('?', rl_outstream); \
5391acd27e7Smillert 	  printed_len += 2; \
5401acd27e7Smillert 	} \
5411acd27e7Smillert       else \
5421acd27e7Smillert 	{ \
5431acd27e7Smillert 	  putc (c, rl_outstream); \
5441acd27e7Smillert 	  printed_len++; \
5451acd27e7Smillert 	} \
5461acd27e7Smillert     } while (0)
5471acd27e7Smillert 
5481acd27e7Smillert static int
print_filename(to_print,full_pathname)5491acd27e7Smillert print_filename (to_print, full_pathname)
5501acd27e7Smillert      char *to_print, *full_pathname;
5511acd27e7Smillert {
5521acd27e7Smillert   int printed_len = 0;
5531acd27e7Smillert #if !defined (VISIBLE_STATS)
5541acd27e7Smillert   char *s;
5551acd27e7Smillert 
5561acd27e7Smillert   for (s = to_print; *s; s++)
5571acd27e7Smillert     {
5581acd27e7Smillert       PUTX (*s);
5591acd27e7Smillert     }
5601acd27e7Smillert #else
5611acd27e7Smillert   char *s, c, *new_full_pathname;
56263bef317Sbeck   int extension_char;
5631acd27e7Smillert 
5641acd27e7Smillert   for (s = to_print; *s; s++)
5651acd27e7Smillert     {
5661acd27e7Smillert       PUTX (*s);
5671acd27e7Smillert     }
5681acd27e7Smillert 
5691acd27e7Smillert  if (rl_filename_completion_desired && rl_visible_stats)
5701acd27e7Smillert     {
5711acd27e7Smillert       /* If to_print != full_pathname, to_print is the basename of the
5721acd27e7Smillert 	 path passed.  In this case, we try to expand the directory
5731acd27e7Smillert 	 name before checking for the stat character. */
5741acd27e7Smillert       if (to_print != full_pathname)
5751acd27e7Smillert 	{
5761acd27e7Smillert 	  /* Terminate the directory name. */
5771acd27e7Smillert 	  c = to_print[-1];
5781acd27e7Smillert 	  to_print[-1] = '\0';
5791acd27e7Smillert 
5801acd27e7Smillert 	  /* If setting the last slash in full_pathname to a NUL results in
5811acd27e7Smillert 	     full_pathname being the empty string, we are trying to complete
5821acd27e7Smillert 	     files in the root directory.  If we pass a null string to the
5831acd27e7Smillert 	     bash directory completion hook, for example, it will expand it
5841acd27e7Smillert 	     to the current directory.  We just want the `/'. */
5851acd27e7Smillert 	  s = tilde_expand (full_pathname && *full_pathname ? full_pathname : "/");
5861acd27e7Smillert 	  if (rl_directory_completion_hook)
5871acd27e7Smillert 	    (*rl_directory_completion_hook) (&s);
58863bef317Sbeck 	  if (asprintf(&new_full_pathname, "%s/%s", s, to_print) == -1)
58963bef317Sbeck 		  memory_error_and_abort("asprintf");
5901acd27e7Smillert 	  extension_char = stat_char (new_full_pathname);
5911acd27e7Smillert 	  free (new_full_pathname);
5921acd27e7Smillert 	  to_print[-1] = c;
5931acd27e7Smillert 	}
5941acd27e7Smillert       else
5951acd27e7Smillert 	{
5961acd27e7Smillert 	  s = tilde_expand (full_pathname);
5971acd27e7Smillert 	  extension_char = stat_char (s);
5981acd27e7Smillert 	}
5991acd27e7Smillert 
6001acd27e7Smillert       free (s);
6011acd27e7Smillert       if (extension_char)
6021acd27e7Smillert 	{
6031acd27e7Smillert 	  putc (extension_char, rl_outstream);
6041acd27e7Smillert 	  printed_len++;
6051acd27e7Smillert 	}
6061acd27e7Smillert     }
6071acd27e7Smillert #endif /* VISIBLE_STATS */
6081acd27e7Smillert   return printed_len;
6091acd27e7Smillert }
6101acd27e7Smillert 
6111acd27e7Smillert static char *
rl_quote_filename(s,rtype,qcp)6121acd27e7Smillert rl_quote_filename (s, rtype, qcp)
6131acd27e7Smillert      char *s;
6141acd27e7Smillert      int rtype;
6151acd27e7Smillert      char *qcp;
6161acd27e7Smillert {
6171acd27e7Smillert   char *r;
61863bef317Sbeck   int len = strlen(s) + 2;
6191acd27e7Smillert 
620af70c2dfSkettenis   r = (char *)xmalloc (len);
6211acd27e7Smillert   *r = *rl_completer_quote_characters;
62263bef317Sbeck   strlcpy (r + 1, s, len - 1);
6231acd27e7Smillert   if (qcp)
6241acd27e7Smillert     *qcp = *rl_completer_quote_characters;
6251acd27e7Smillert   return r;
6261acd27e7Smillert }
6271acd27e7Smillert 
6281acd27e7Smillert /* Find the bounds of the current word for completion purposes, and leave
6291acd27e7Smillert    rl_point set to the end of the word.  This function skips quoted
6301acd27e7Smillert    substrings (characters between matched pairs of characters in
631af70c2dfSkettenis    rl_completer_quote_characters).  First we try to find an unclosed
6321acd27e7Smillert    quoted substring on which to do matching.  If one is not found, we use
6331acd27e7Smillert    the word break characters to find the boundaries of the current word.
6341acd27e7Smillert    We call an application-specific function to decide whether or not a
6351acd27e7Smillert    particular word break character is quoted; if that function returns a
6361acd27e7Smillert    non-zero result, the character does not break a word.  This function
6371acd27e7Smillert    returns the opening quote character if we found an unclosed quoted
6381acd27e7Smillert    substring, '\0' otherwise.  FP, if non-null, is set to a value saying
6391acd27e7Smillert    which (shell-like) quote characters we found (single quote, double
6401acd27e7Smillert    quote, or backslash) anywhere in the string.  DP, if non-null, is set to
6411acd27e7Smillert    the value of the delimiter character that caused a word break. */
6421acd27e7Smillert 
643af70c2dfSkettenis char
_rl_find_completion_word(fp,dp)644af70c2dfSkettenis _rl_find_completion_word (fp, dp)
6451acd27e7Smillert      int *fp, *dp;
6461acd27e7Smillert {
6471acd27e7Smillert   int scan, end, found_quote, delimiter, pass_next, isbrk;
6481acd27e7Smillert   char quote_char;
6491acd27e7Smillert 
6501acd27e7Smillert   end = rl_point;
6511acd27e7Smillert   found_quote = delimiter = 0;
6521acd27e7Smillert   quote_char = '\0';
6531acd27e7Smillert 
6541acd27e7Smillert   if (rl_completer_quote_characters)
6551acd27e7Smillert     {
6561acd27e7Smillert       /* We have a list of characters which can be used in pairs to
6571acd27e7Smillert 	 quote substrings for the completer.  Try to find the start
6581acd27e7Smillert 	 of an unclosed quoted substring. */
6591acd27e7Smillert       /* FOUND_QUOTE is set so we know what kind of quotes we found. */
6601acd27e7Smillert       for (scan = pass_next = 0; scan < end; scan++)
6611acd27e7Smillert 	{
6621acd27e7Smillert 	  if (pass_next)
6631acd27e7Smillert 	    {
6641acd27e7Smillert 	      pass_next = 0;
6651acd27e7Smillert 	      continue;
6661acd27e7Smillert 	    }
6671acd27e7Smillert 
668af70c2dfSkettenis 	  /* Shell-like semantics for single quotes -- don't allow backslash
669af70c2dfSkettenis 	     to quote anything in single quotes, especially not the closing
670af70c2dfSkettenis 	     quote.  If you don't like this, take out the check on the value
671af70c2dfSkettenis 	     of quote_char. */
672af70c2dfSkettenis 	  if (quote_char != '\'' && rl_line_buffer[scan] == '\\')
6731acd27e7Smillert 	    {
6741acd27e7Smillert 	      pass_next = 1;
6751acd27e7Smillert 	      found_quote |= RL_QF_BACKSLASH;
6761acd27e7Smillert 	      continue;
6771acd27e7Smillert 	    }
6781acd27e7Smillert 
6791acd27e7Smillert 	  if (quote_char != '\0')
6801acd27e7Smillert 	    {
6811acd27e7Smillert 	      /* Ignore everything until the matching close quote char. */
6821acd27e7Smillert 	      if (rl_line_buffer[scan] == quote_char)
6831acd27e7Smillert 		{
6841acd27e7Smillert 		  /* Found matching close.  Abandon this substring. */
6851acd27e7Smillert 		  quote_char = '\0';
6861acd27e7Smillert 		  rl_point = end;
6871acd27e7Smillert 		}
6881acd27e7Smillert 	    }
6891acd27e7Smillert 	  else if (strchr (rl_completer_quote_characters, rl_line_buffer[scan]))
6901acd27e7Smillert 	    {
6911acd27e7Smillert 	      /* Found start of a quoted substring. */
6921acd27e7Smillert 	      quote_char = rl_line_buffer[scan];
6931acd27e7Smillert 	      rl_point = scan + 1;
6941acd27e7Smillert 	      /* Shell-like quoting conventions. */
6951acd27e7Smillert 	      if (quote_char == '\'')
6961acd27e7Smillert 		found_quote |= RL_QF_SINGLE_QUOTE;
6971acd27e7Smillert 	      else if (quote_char == '"')
6981acd27e7Smillert 		found_quote |= RL_QF_DOUBLE_QUOTE;
699af70c2dfSkettenis 	      else
700af70c2dfSkettenis 		found_quote |= RL_QF_OTHER_QUOTE;
7011acd27e7Smillert 	    }
7021acd27e7Smillert 	}
7031acd27e7Smillert     }
7041acd27e7Smillert 
7051acd27e7Smillert   if (rl_point == end && quote_char == '\0')
7061acd27e7Smillert     {
7071acd27e7Smillert       /* We didn't find an unclosed quoted substring upon which to do
7081acd27e7Smillert          completion, so use the word break characters to find the
7091acd27e7Smillert          substring on which to complete. */
710af70c2dfSkettenis #if defined (HANDLE_MULTIBYTE)
711af70c2dfSkettenis       while (rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_ANY))
712af70c2dfSkettenis #else
7131acd27e7Smillert       while (--rl_point)
714af70c2dfSkettenis #endif
7151acd27e7Smillert 	{
7161acd27e7Smillert 	  scan = rl_line_buffer[rl_point];
7171acd27e7Smillert 
7181acd27e7Smillert 	  if (strchr (rl_completer_word_break_characters, scan) == 0)
7191acd27e7Smillert 	    continue;
7201acd27e7Smillert 
7211acd27e7Smillert 	  /* Call the application-specific function to tell us whether
7221acd27e7Smillert 	     this word break character is quoted and should be skipped. */
7231acd27e7Smillert 	  if (rl_char_is_quoted_p && found_quote &&
7241acd27e7Smillert 	      (*rl_char_is_quoted_p) (rl_line_buffer, rl_point))
7251acd27e7Smillert 	    continue;
7261acd27e7Smillert 
7271acd27e7Smillert 	  /* Convoluted code, but it avoids an n^2 algorithm with calls
7281acd27e7Smillert 	     to char_is_quoted. */
7291acd27e7Smillert 	  break;
7301acd27e7Smillert 	}
7311acd27e7Smillert     }
7321acd27e7Smillert 
7331acd27e7Smillert   /* If we are at an unquoted word break, then advance past it. */
7341acd27e7Smillert   scan = rl_line_buffer[rl_point];
7351acd27e7Smillert 
7361acd27e7Smillert   /* If there is an application-specific function to say whether or not
7371acd27e7Smillert      a character is quoted and we found a quote character, let that
7381acd27e7Smillert      function decide whether or not a character is a word break, even
7391acd27e7Smillert      if it is found in rl_completer_word_break_characters.  Don't bother
7401acd27e7Smillert      if we're at the end of the line, though. */
7411acd27e7Smillert   if (scan)
7421acd27e7Smillert     {
7431acd27e7Smillert       if (rl_char_is_quoted_p)
7441acd27e7Smillert 	isbrk = (found_quote == 0 ||
7451acd27e7Smillert 		(*rl_char_is_quoted_p) (rl_line_buffer, rl_point) == 0) &&
7461acd27e7Smillert 		strchr (rl_completer_word_break_characters, scan) != 0;
7471acd27e7Smillert       else
7481acd27e7Smillert 	isbrk = strchr (rl_completer_word_break_characters, scan) != 0;
7491acd27e7Smillert 
7501acd27e7Smillert       if (isbrk)
7511acd27e7Smillert 	{
7521acd27e7Smillert 	  /* If the character that caused the word break was a quoting
7531acd27e7Smillert 	     character, then remember it as the delimiter. */
7541acd27e7Smillert 	  if (rl_basic_quote_characters &&
7551acd27e7Smillert 	      strchr (rl_basic_quote_characters, scan) &&
7561acd27e7Smillert 	      (end - rl_point) > 1)
7571acd27e7Smillert 	    delimiter = scan;
7581acd27e7Smillert 
7591acd27e7Smillert 	  /* If the character isn't needed to determine something special
7601acd27e7Smillert 	     about what kind of completion to perform, then advance past it. */
7611acd27e7Smillert 	  if (rl_special_prefixes == 0 || strchr (rl_special_prefixes, scan) == 0)
7621acd27e7Smillert 	    rl_point++;
7631acd27e7Smillert 	}
7641acd27e7Smillert     }
7651acd27e7Smillert 
7661acd27e7Smillert   if (fp)
7671acd27e7Smillert     *fp = found_quote;
7681acd27e7Smillert   if (dp)
7691acd27e7Smillert     *dp = delimiter;
7701acd27e7Smillert 
7711acd27e7Smillert   return (quote_char);
7721acd27e7Smillert }
7731acd27e7Smillert 
7741acd27e7Smillert static char **
gen_completion_matches(text,start,end,our_func,found_quote,quote_char)7751acd27e7Smillert gen_completion_matches (text, start, end, our_func, found_quote, quote_char)
7761acd27e7Smillert      char *text;
7771acd27e7Smillert      int start, end;
778af70c2dfSkettenis      rl_compentry_func_t *our_func;
7791acd27e7Smillert      int found_quote, quote_char;
7801acd27e7Smillert {
7811acd27e7Smillert   char **matches, *temp;
7821acd27e7Smillert 
7831acd27e7Smillert   /* If the user wants to TRY to complete, but then wants to give
7841acd27e7Smillert      up and use the default completion function, they set the
7851acd27e7Smillert      variable rl_attempted_completion_function. */
7861acd27e7Smillert   if (rl_attempted_completion_function)
7871acd27e7Smillert     {
7881acd27e7Smillert       matches = (*rl_attempted_completion_function) (text, start, end);
7891acd27e7Smillert 
7901acd27e7Smillert       if (matches || rl_attempted_completion_over)
7911acd27e7Smillert 	{
7921acd27e7Smillert 	  rl_attempted_completion_over = 0;
7931acd27e7Smillert 	  return (matches);
7941acd27e7Smillert 	}
7951acd27e7Smillert     }
7961acd27e7Smillert 
7971acd27e7Smillert   /* Beware -- we're stripping the quotes here.  Do this only if we know
7981acd27e7Smillert      we are doing filename completion and the application has defined a
7991acd27e7Smillert      filename dequoting function. */
8001acd27e7Smillert   temp = (char *)NULL;
8011acd27e7Smillert 
802af70c2dfSkettenis   if (found_quote && our_func == rl_filename_completion_function &&
8031acd27e7Smillert       rl_filename_dequoting_function)
8041acd27e7Smillert     {
8051acd27e7Smillert       /* delete single and double quotes */
8061acd27e7Smillert       temp = (*rl_filename_dequoting_function) (text, quote_char);
8071acd27e7Smillert       text = temp;	/* not freeing text is not a memory leak */
8081acd27e7Smillert     }
8091acd27e7Smillert 
810af70c2dfSkettenis   matches = rl_completion_matches (text, our_func);
8111acd27e7Smillert   FREE (temp);
8121acd27e7Smillert   return matches;
8131acd27e7Smillert }
8141acd27e7Smillert 
8151acd27e7Smillert /* Filter out duplicates in MATCHES.  This frees up the strings in
8161acd27e7Smillert    MATCHES. */
8171acd27e7Smillert static char **
remove_duplicate_matches(matches)8181acd27e7Smillert remove_duplicate_matches (matches)
8191acd27e7Smillert      char **matches;
8201acd27e7Smillert {
8211acd27e7Smillert   char *lowest_common;
8221acd27e7Smillert   int i, j, newlen;
8231acd27e7Smillert   char dead_slot;
8241acd27e7Smillert   char **temp_array;
8251acd27e7Smillert 
8261acd27e7Smillert   /* Sort the items. */
8271acd27e7Smillert   for (i = 0; matches[i]; i++)
8281acd27e7Smillert     ;
8291acd27e7Smillert 
8301acd27e7Smillert   /* Sort the array without matches[0], since we need it to
8311acd27e7Smillert      stay in place no matter what. */
8321acd27e7Smillert   if (i)
8331acd27e7Smillert     qsort (matches+1, i-1, sizeof (char *), (QSFUNC *)_rl_qsort_string_compare);
8341acd27e7Smillert 
8351acd27e7Smillert   /* Remember the lowest common denominator for it may be unique. */
8361acd27e7Smillert   lowest_common = savestring (matches[0]);
8371acd27e7Smillert 
8381acd27e7Smillert   for (i = newlen = 0; matches[i + 1]; i++)
8391acd27e7Smillert     {
8401acd27e7Smillert       if (strcmp (matches[i], matches[i + 1]) == 0)
8411acd27e7Smillert 	{
8421acd27e7Smillert 	  free (matches[i]);
8431acd27e7Smillert 	  matches[i] = (char *)&dead_slot;
8441acd27e7Smillert 	}
8451acd27e7Smillert       else
8461acd27e7Smillert 	newlen++;
8471acd27e7Smillert     }
8481acd27e7Smillert 
8491acd27e7Smillert   /* We have marked all the dead slots with (char *)&dead_slot.
8501acd27e7Smillert      Copy all the non-dead entries into a new array. */
8511acd27e7Smillert   temp_array = (char **)xmalloc ((3 + newlen) * sizeof (char *));
8521acd27e7Smillert   for (i = j = 1; matches[i]; i++)
8531acd27e7Smillert     {
8541acd27e7Smillert       if (matches[i] != (char *)&dead_slot)
8551acd27e7Smillert 	temp_array[j++] = matches[i];
8561acd27e7Smillert     }
8571acd27e7Smillert   temp_array[j] = (char *)NULL;
8581acd27e7Smillert 
8591acd27e7Smillert   if (matches[0] != (char *)&dead_slot)
8601acd27e7Smillert     free (matches[0]);
8611acd27e7Smillert 
8621acd27e7Smillert   /* Place the lowest common denominator back in [0]. */
8631acd27e7Smillert   temp_array[0] = lowest_common;
8641acd27e7Smillert 
8651acd27e7Smillert   /* If there is one string left, and it is identical to the
8661acd27e7Smillert      lowest common denominator, then the LCD is the string to
8671acd27e7Smillert      insert. */
8681acd27e7Smillert   if (j == 2 && strcmp (temp_array[0], temp_array[1]) == 0)
8691acd27e7Smillert     {
8701acd27e7Smillert       free (temp_array[1]);
8711acd27e7Smillert       temp_array[1] = (char *)NULL;
8721acd27e7Smillert     }
8731acd27e7Smillert   return (temp_array);
8741acd27e7Smillert }
8751acd27e7Smillert 
8761acd27e7Smillert /* Find the common prefix of the list of matches, and put it into
8771acd27e7Smillert    matches[0]. */
8781acd27e7Smillert static int
compute_lcd_of_matches(match_list,matches,text)8791acd27e7Smillert compute_lcd_of_matches (match_list, matches, text)
8801acd27e7Smillert      char **match_list;
8811acd27e7Smillert      int matches;
882af70c2dfSkettenis      const char *text;
8831acd27e7Smillert {
8841acd27e7Smillert   register int i, c1, c2, si;
8851acd27e7Smillert   int low;		/* Count of max-matched characters. */
886af70c2dfSkettenis #if defined (HANDLE_MULTIBYTE)
887af70c2dfSkettenis   int v;
888af70c2dfSkettenis   mbstate_t ps1, ps2;
889af70c2dfSkettenis   wchar_t wc1, wc2;
890af70c2dfSkettenis #endif
8911acd27e7Smillert 
8921acd27e7Smillert   /* If only one match, just use that.  Otherwise, compare each
8931acd27e7Smillert      member of the list with the next, finding out where they
8941acd27e7Smillert      stop matching. */
8951acd27e7Smillert   if (matches == 1)
8961acd27e7Smillert     {
8971acd27e7Smillert       match_list[0] = match_list[1];
8981acd27e7Smillert       match_list[1] = (char *)NULL;
8991acd27e7Smillert       return 1;
9001acd27e7Smillert     }
9011acd27e7Smillert 
9021acd27e7Smillert   for (i = 1, low = 100000; i < matches; i++)
9031acd27e7Smillert     {
904af70c2dfSkettenis #if defined (HANDLE_MULTIBYTE)
905af70c2dfSkettenis       if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
906af70c2dfSkettenis 	{
907af70c2dfSkettenis 	  memset (&ps1, 0, sizeof (mbstate_t));
908af70c2dfSkettenis 	  memset (&ps2, 0, sizeof (mbstate_t));
909af70c2dfSkettenis 	}
910af70c2dfSkettenis #endif
9111acd27e7Smillert       if (_rl_completion_case_fold)
9121acd27e7Smillert 	{
9131acd27e7Smillert 	  for (si = 0;
9141acd27e7Smillert 	       (c1 = _rl_to_lower(match_list[i][si])) &&
9151acd27e7Smillert 	       (c2 = _rl_to_lower(match_list[i + 1][si]));
9161acd27e7Smillert 	       si++)
917af70c2dfSkettenis #if defined (HANDLE_MULTIBYTE)
918af70c2dfSkettenis 	    if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
919af70c2dfSkettenis 	      {
920af70c2dfSkettenis 		v = mbrtowc (&wc1, match_list[i]+si, strlen (match_list[i]+si), &ps1);
921af70c2dfSkettenis 		mbrtowc (&wc2, match_list[i+1]+si, strlen (match_list[i+1]+si), &ps2);
922af70c2dfSkettenis 		wc1 = towlower (wc1);
923af70c2dfSkettenis 		wc2 = towlower (wc2);
924af70c2dfSkettenis 		if (wc1 != wc2)
925af70c2dfSkettenis 		  break;
926af70c2dfSkettenis 		else if (v > 1)
927af70c2dfSkettenis 		  si += v - 1;
928af70c2dfSkettenis 	      }
929af70c2dfSkettenis 	    else
930af70c2dfSkettenis #endif
9311acd27e7Smillert 	    if (c1 != c2)
9321acd27e7Smillert 	      break;
9331acd27e7Smillert 	}
9341acd27e7Smillert       else
9351acd27e7Smillert 	{
9361acd27e7Smillert 	  for (si = 0;
9371acd27e7Smillert 	       (c1 = match_list[i][si]) &&
9381acd27e7Smillert 	       (c2 = match_list[i + 1][si]);
9391acd27e7Smillert 	       si++)
940af70c2dfSkettenis #if defined (HANDLE_MULTIBYTE)
941af70c2dfSkettenis 	    if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
942af70c2dfSkettenis 	      {
943af70c2dfSkettenis 		mbstate_t ps_back = ps1;
944af70c2dfSkettenis 		if (!_rl_compare_chars (match_list[i], si, &ps1, match_list[i+1], si, &ps2))
945af70c2dfSkettenis 		  break;
946af70c2dfSkettenis 		else if ((v = _rl_get_char_len (&match_list[i][si], &ps_back)) > 1)
947af70c2dfSkettenis 		  si += v - 1;
948af70c2dfSkettenis 	      }
949af70c2dfSkettenis 	    else
950af70c2dfSkettenis #endif
9511acd27e7Smillert 	    if (c1 != c2)
9521acd27e7Smillert 	      break;
9531acd27e7Smillert 	}
9541acd27e7Smillert 
9551acd27e7Smillert       if (low > si)
9561acd27e7Smillert 	low = si;
9571acd27e7Smillert     }
9581acd27e7Smillert 
9591acd27e7Smillert   /* If there were multiple matches, but none matched up to even the
9601acd27e7Smillert      first character, and the user typed something, use that as the
9611acd27e7Smillert      value of matches[0]. */
9621acd27e7Smillert   if (low == 0 && text && *text)
9631acd27e7Smillert     {
96463bef317Sbeck       match_list[0] = strdup(text);
96563bef317Sbeck       if (match_list[0] == NULL)
96663bef317Sbeck 	      memory_error_and_abort("strdup");
9671acd27e7Smillert     }
9681acd27e7Smillert   else
9691acd27e7Smillert     {
970af70c2dfSkettenis       match_list[0] = (char *)xmalloc (low + 1);
971af70c2dfSkettenis 
972af70c2dfSkettenis       /* XXX - this might need changes in the presence of multibyte chars */
973af70c2dfSkettenis 
974af70c2dfSkettenis       /* If we are ignoring case, try to preserve the case of the string
975af70c2dfSkettenis 	 the user typed in the face of multiple matches differing in case. */
976af70c2dfSkettenis       if (_rl_completion_case_fold)
977af70c2dfSkettenis 	{
978af70c2dfSkettenis 	  /* sort the list to get consistent answers. */
979af70c2dfSkettenis 	  qsort (match_list+1, matches, sizeof(char *), (QSFUNC *)_rl_qsort_string_compare);
980af70c2dfSkettenis 
981af70c2dfSkettenis 	  si = strlen (text);
982af70c2dfSkettenis 	  if (si <= low)
983af70c2dfSkettenis 	    {
984af70c2dfSkettenis 	      for (i = 1; i <= matches; i++)
985af70c2dfSkettenis 		if (strncmp (match_list[i], text, si) == 0)
986af70c2dfSkettenis 		  {
987af70c2dfSkettenis 		    strncpy (match_list[0], match_list[i], low);
988af70c2dfSkettenis 		    break;
989af70c2dfSkettenis 		  }
990af70c2dfSkettenis 	      /* no casematch, use first entry */
991af70c2dfSkettenis 	      if (i > matches)
9921acd27e7Smillert 		strncpy (match_list[0], match_list[1], low);
993af70c2dfSkettenis 	    }
994af70c2dfSkettenis 	  else
995af70c2dfSkettenis 	    /* otherwise, just use the text the user typed. */
996af70c2dfSkettenis 	    strncpy (match_list[0], text, low);
997af70c2dfSkettenis 	}
998af70c2dfSkettenis       else
999af70c2dfSkettenis         strncpy (match_list[0], match_list[1], low);
1000af70c2dfSkettenis 
10011acd27e7Smillert       match_list[0][low] = '\0';
10021acd27e7Smillert     }
10031acd27e7Smillert 
10041acd27e7Smillert   return matches;
10051acd27e7Smillert }
10061acd27e7Smillert 
10071acd27e7Smillert static int
postprocess_matches(matchesp,matching_filenames)10081acd27e7Smillert postprocess_matches (matchesp, matching_filenames)
10091acd27e7Smillert      char ***matchesp;
10101acd27e7Smillert      int matching_filenames;
10111acd27e7Smillert {
10121acd27e7Smillert   char *t, **matches, **temp_matches;
10131acd27e7Smillert   int nmatch, i;
10141acd27e7Smillert 
10151acd27e7Smillert   matches = *matchesp;
10161acd27e7Smillert 
1017af70c2dfSkettenis   if (matches == 0)
1018af70c2dfSkettenis     return 0;
1019af70c2dfSkettenis 
10201acd27e7Smillert   /* It seems to me that in all the cases we handle we would like
10211acd27e7Smillert      to ignore duplicate possiblilities.  Scan for the text to
10221acd27e7Smillert      insert being identical to the other completions. */
10231acd27e7Smillert   if (rl_ignore_completion_duplicates)
10241acd27e7Smillert     {
10251acd27e7Smillert       temp_matches = remove_duplicate_matches (matches);
10261acd27e7Smillert       free (matches);
10271acd27e7Smillert       matches = temp_matches;
10281acd27e7Smillert     }
10291acd27e7Smillert 
10301acd27e7Smillert   /* If we are matching filenames, then here is our chance to
10311acd27e7Smillert      do clever processing by re-examining the list.  Call the
10321acd27e7Smillert      ignore function with the array as a parameter.  It can
10331acd27e7Smillert      munge the array, deleting matches as it desires. */
10341acd27e7Smillert   if (rl_ignore_some_completions_function && matching_filenames)
10351acd27e7Smillert     {
10361acd27e7Smillert       for (nmatch = 1; matches[nmatch]; nmatch++)
10371acd27e7Smillert 	;
10381acd27e7Smillert       (void)(*rl_ignore_some_completions_function) (matches);
10391acd27e7Smillert       if (matches == 0 || matches[0] == 0)
10401acd27e7Smillert 	{
10411acd27e7Smillert 	  FREE (matches);
10421acd27e7Smillert 	  *matchesp = (char **)0;
10431acd27e7Smillert 	  return 0;
10441acd27e7Smillert         }
10451acd27e7Smillert       else
10461acd27e7Smillert 	{
10471acd27e7Smillert 	  /* If we removed some matches, recompute the common prefix. */
10481acd27e7Smillert 	  for (i = 1; matches[i]; i++)
10491acd27e7Smillert 	    ;
10501acd27e7Smillert 	  if (i > 1 && i < nmatch)
10511acd27e7Smillert 	    {
10521acd27e7Smillert 	      t = matches[0];
10531acd27e7Smillert 	      compute_lcd_of_matches (matches, i - 1, t);
10541acd27e7Smillert 	      FREE (t);
10551acd27e7Smillert 	    }
10561acd27e7Smillert 	}
10571acd27e7Smillert     }
10581acd27e7Smillert 
10591acd27e7Smillert   *matchesp = matches;
10601acd27e7Smillert   return (1);
10611acd27e7Smillert }
10621acd27e7Smillert 
10631acd27e7Smillert /* A convenience function for displaying a list of strings in
10641acd27e7Smillert    columnar format on readline's output stream.  MATCHES is the list
10651acd27e7Smillert    of strings, in argv format, LEN is the number of strings in MATCHES,
10661acd27e7Smillert    and MAX is the length of the longest string in MATCHES. */
10671acd27e7Smillert void
rl_display_match_list(matches,len,max)10681acd27e7Smillert rl_display_match_list (matches, len, max)
10691acd27e7Smillert      char **matches;
10701acd27e7Smillert      int len, max;
10711acd27e7Smillert {
1072af70c2dfSkettenis   int count, limit, printed_len, lines;
10731acd27e7Smillert   int i, j, k, l;
10741acd27e7Smillert   char *temp;
10751acd27e7Smillert 
10761acd27e7Smillert   /* How many items of MAX length can we fit in the screen window? */
10771acd27e7Smillert   max += 2;
1078af70c2dfSkettenis   limit = _rl_screenwidth / max;
1079af70c2dfSkettenis   if (limit != 1 && (limit * max == _rl_screenwidth))
10801acd27e7Smillert     limit--;
10811acd27e7Smillert 
1082af70c2dfSkettenis   /* Avoid a possible floating exception.  If max > _rl_screenwidth,
10831acd27e7Smillert      limit will be 0 and a divide-by-zero fault will result. */
10841acd27e7Smillert   if (limit == 0)
10851acd27e7Smillert     limit = 1;
10861acd27e7Smillert 
10871acd27e7Smillert   /* How many iterations of the printing loop? */
10881acd27e7Smillert   count = (len + (limit - 1)) / limit;
10891acd27e7Smillert 
10901acd27e7Smillert   /* Watch out for special case.  If LEN is less than LIMIT, then
10911acd27e7Smillert      just do the inner printing loop.
10921acd27e7Smillert 	   0 < len <= limit  implies  count = 1. */
10931acd27e7Smillert 
10941acd27e7Smillert   /* Sort the items if they are not already sorted. */
10951acd27e7Smillert   if (rl_ignore_completion_duplicates == 0)
10961acd27e7Smillert     qsort (matches + 1, len, sizeof (char *), (QSFUNC *)_rl_qsort_string_compare);
10971acd27e7Smillert 
1098af70c2dfSkettenis   rl_crlf ();
10991acd27e7Smillert 
1100af70c2dfSkettenis   lines = 0;
11011acd27e7Smillert   if (_rl_print_completions_horizontally == 0)
11021acd27e7Smillert     {
11031acd27e7Smillert       /* Print the sorted items, up-and-down alphabetically, like ls. */
11041acd27e7Smillert       for (i = 1; i <= count; i++)
11051acd27e7Smillert 	{
11061acd27e7Smillert 	  for (j = 0, l = i; j < limit; j++)
11071acd27e7Smillert 	    {
11081acd27e7Smillert 	      if (l > len || matches[l] == 0)
11091acd27e7Smillert 		break;
11101acd27e7Smillert 	      else
11111acd27e7Smillert 		{
11121acd27e7Smillert 		  temp = printable_part (matches[l]);
11131acd27e7Smillert 		  printed_len = print_filename (temp, matches[l]);
11141acd27e7Smillert 
11151acd27e7Smillert 		  if (j + 1 < limit)
11161acd27e7Smillert 		    for (k = 0; k < max - printed_len; k++)
11171acd27e7Smillert 		      putc (' ', rl_outstream);
11181acd27e7Smillert 		}
11191acd27e7Smillert 	      l += count;
11201acd27e7Smillert 	    }
1121af70c2dfSkettenis 	  rl_crlf ();
1122af70c2dfSkettenis 	  lines++;
1123af70c2dfSkettenis 	  if (_rl_page_completions && lines >= (_rl_screenheight - 1) && i < count)
1124af70c2dfSkettenis 	    {
1125af70c2dfSkettenis 	      lines = _rl_internal_pager (lines);
1126af70c2dfSkettenis 	      if (lines < 0)
1127af70c2dfSkettenis 		return;
1128af70c2dfSkettenis 	    }
11291acd27e7Smillert 	}
11301acd27e7Smillert     }
11311acd27e7Smillert   else
11321acd27e7Smillert     {
11331acd27e7Smillert       /* Print the sorted items, across alphabetically, like ls -x. */
11341acd27e7Smillert       for (i = 1; matches[i]; i++)
11351acd27e7Smillert 	{
11361acd27e7Smillert 	  temp = printable_part (matches[i]);
11371acd27e7Smillert 	  printed_len = print_filename (temp, matches[i]);
11381acd27e7Smillert 	  /* Have we reached the end of this line? */
11391acd27e7Smillert 	  if (matches[i+1])
11401acd27e7Smillert 	    {
11411acd27e7Smillert 	      if (i && (limit > 1) && (i % limit) == 0)
1142af70c2dfSkettenis 		{
1143af70c2dfSkettenis 		  rl_crlf ();
1144af70c2dfSkettenis 		  lines++;
1145af70c2dfSkettenis 		  if (_rl_page_completions && lines >= _rl_screenheight - 1)
1146af70c2dfSkettenis 		    {
1147af70c2dfSkettenis 		      lines = _rl_internal_pager (lines);
1148af70c2dfSkettenis 		      if (lines < 0)
1149af70c2dfSkettenis 			return;
1150af70c2dfSkettenis 		    }
1151af70c2dfSkettenis 		}
11521acd27e7Smillert 	      else
11531acd27e7Smillert 		for (k = 0; k < max - printed_len; k++)
11541acd27e7Smillert 		  putc (' ', rl_outstream);
11551acd27e7Smillert 	    }
11561acd27e7Smillert 	}
1157af70c2dfSkettenis       rl_crlf ();
11581acd27e7Smillert     }
11591acd27e7Smillert }
11601acd27e7Smillert 
11611acd27e7Smillert /* Display MATCHES, a list of matching filenames in argv format.  This
11621acd27e7Smillert    handles the simple case -- a single match -- first.  If there is more
11631acd27e7Smillert    than one match, we compute the number of strings in the list and the
11641acd27e7Smillert    length of the longest string, which will be needed by the display
11651acd27e7Smillert    function.  If the application wants to handle displaying the list of
11661acd27e7Smillert    matches itself, it sets RL_COMPLETION_DISPLAY_MATCHES_HOOK to the
11671acd27e7Smillert    address of a function, and we just call it.  If we're handling the
11681acd27e7Smillert    display ourselves, we just call rl_display_match_list.  We also check
11691acd27e7Smillert    that the list of matches doesn't exceed the user-settable threshold,
11701acd27e7Smillert    and ask the user if he wants to see the list if there are more matches
11711acd27e7Smillert    than RL_COMPLETION_QUERY_ITEMS. */
11721acd27e7Smillert static void
display_matches(matches)11731acd27e7Smillert display_matches (matches)
11741acd27e7Smillert      char **matches;
11751acd27e7Smillert {
11761acd27e7Smillert   int len, max, i;
11771acd27e7Smillert   char *temp;
11781acd27e7Smillert 
11791acd27e7Smillert   /* Move to the last visible line of a possibly-multiple-line command. */
11801acd27e7Smillert   _rl_move_vert (_rl_vis_botlin);
11811acd27e7Smillert 
11821acd27e7Smillert   /* Handle simple case first.  What if there is only one answer? */
11831acd27e7Smillert   if (matches[1] == 0)
11841acd27e7Smillert     {
11851acd27e7Smillert       temp = printable_part (matches[0]);
1186af70c2dfSkettenis       rl_crlf ();
11871acd27e7Smillert       print_filename (temp, matches[0]);
1188af70c2dfSkettenis       rl_crlf ();
11891acd27e7Smillert 
11901acd27e7Smillert       rl_forced_update_display ();
11911acd27e7Smillert       rl_display_fixed = 1;
11921acd27e7Smillert 
11931acd27e7Smillert       return;
11941acd27e7Smillert     }
11951acd27e7Smillert 
11961acd27e7Smillert   /* There is more than one answer.  Find out how many there are,
11971acd27e7Smillert      and find the maximum printed length of a single entry. */
11981acd27e7Smillert   for (max = 0, i = 1; matches[i]; i++)
11991acd27e7Smillert     {
12001acd27e7Smillert       temp = printable_part (matches[i]);
12011acd27e7Smillert       len = strlen (temp);
12021acd27e7Smillert 
12031acd27e7Smillert       if (len > max)
12041acd27e7Smillert 	max = len;
12051acd27e7Smillert     }
12061acd27e7Smillert 
12071acd27e7Smillert   len = i - 1;
12081acd27e7Smillert 
12091acd27e7Smillert   /* If the caller has defined a display hook, then call that now. */
12101acd27e7Smillert   if (rl_completion_display_matches_hook)
12111acd27e7Smillert     {
12121acd27e7Smillert       (*rl_completion_display_matches_hook) (matches, len, max);
12131acd27e7Smillert       return;
12141acd27e7Smillert     }
12151acd27e7Smillert 
12161acd27e7Smillert   /* If there are many items, then ask the user if she really wants to
12171acd27e7Smillert      see them all. */
12181acd27e7Smillert   if (len >= rl_completion_query_items)
12191acd27e7Smillert     {
1220af70c2dfSkettenis       rl_crlf ();
12211acd27e7Smillert       fprintf (rl_outstream, "Display all %d possibilities? (y or n)", len);
12221acd27e7Smillert       fflush (rl_outstream);
1223af70c2dfSkettenis       if (get_y_or_n (0) == 0)
12241acd27e7Smillert 	{
1225af70c2dfSkettenis 	  rl_crlf ();
12261acd27e7Smillert 
12271acd27e7Smillert 	  rl_forced_update_display ();
12281acd27e7Smillert 	  rl_display_fixed = 1;
12291acd27e7Smillert 
12301acd27e7Smillert 	  return;
12311acd27e7Smillert 	}
12321acd27e7Smillert     }
12331acd27e7Smillert 
12341acd27e7Smillert   rl_display_match_list (matches, len, max);
12351acd27e7Smillert 
12361acd27e7Smillert   rl_forced_update_display ();
12371acd27e7Smillert   rl_display_fixed = 1;
12381acd27e7Smillert }
12391acd27e7Smillert 
12401acd27e7Smillert static char *
make_quoted_replacement(match,mtype,qc)12411acd27e7Smillert make_quoted_replacement (match, mtype, qc)
12421acd27e7Smillert      char *match;
12431acd27e7Smillert      int mtype;
12441acd27e7Smillert      char *qc;	/* Pointer to quoting character, if any */
12451acd27e7Smillert {
12461acd27e7Smillert   int should_quote, do_replace;
12471acd27e7Smillert   char *replacement;
12481acd27e7Smillert 
12491acd27e7Smillert   /* If we are doing completion on quoted substrings, and any matches
12501acd27e7Smillert      contain any of the completer_word_break_characters, then auto-
12511acd27e7Smillert      matically prepend the substring with a quote character (just pick
12521acd27e7Smillert      the first one from the list of such) if it does not already begin
12531acd27e7Smillert      with a quote string.  FIXME: Need to remove any such automatically
12541acd27e7Smillert      inserted quote character when it no longer is necessary, such as
12551acd27e7Smillert      if we change the string we are completing on and the new set of
12561acd27e7Smillert      matches don't require a quoted substring. */
12571acd27e7Smillert   replacement = match;
12581acd27e7Smillert 
12591acd27e7Smillert   should_quote = match && rl_completer_quote_characters &&
12601acd27e7Smillert 			rl_filename_completion_desired &&
12611acd27e7Smillert 			rl_filename_quoting_desired;
12621acd27e7Smillert 
12631acd27e7Smillert   if (should_quote)
12641acd27e7Smillert     should_quote = should_quote && (!qc || !*qc ||
12651acd27e7Smillert 		     (rl_completer_quote_characters && strchr (rl_completer_quote_characters, *qc)));
12661acd27e7Smillert 
12671acd27e7Smillert   if (should_quote)
12681acd27e7Smillert     {
12691acd27e7Smillert       /* If there is a single match, see if we need to quote it.
12701acd27e7Smillert          This also checks whether the common prefix of several
12711acd27e7Smillert 	 matches needs to be quoted. */
12721acd27e7Smillert       should_quote = rl_filename_quote_characters
1273af70c2dfSkettenis 			? (_rl_strpbrk (match, rl_filename_quote_characters) != 0)
12741acd27e7Smillert 			: 0;
12751acd27e7Smillert 
12761acd27e7Smillert       do_replace = should_quote ? mtype : NO_MATCH;
12771acd27e7Smillert       /* Quote the replacement, since we found an embedded
12781acd27e7Smillert 	 word break character in a potential match. */
12791acd27e7Smillert       if (do_replace != NO_MATCH && rl_filename_quoting_function)
12801acd27e7Smillert 	replacement = (*rl_filename_quoting_function) (match, do_replace, qc);
12811acd27e7Smillert     }
12821acd27e7Smillert   return (replacement);
12831acd27e7Smillert }
12841acd27e7Smillert 
12851acd27e7Smillert static void
insert_match(match,start,mtype,qc)12861acd27e7Smillert insert_match (match, start, mtype, qc)
12871acd27e7Smillert      char *match;
12881acd27e7Smillert      int start, mtype;
12891acd27e7Smillert      char *qc;
12901acd27e7Smillert {
12911acd27e7Smillert   char *replacement;
12921acd27e7Smillert   char oqc;
12931acd27e7Smillert 
12941acd27e7Smillert   oqc = qc ? *qc : '\0';
12951acd27e7Smillert   replacement = make_quoted_replacement (match, mtype, qc);
12961acd27e7Smillert 
12971acd27e7Smillert   /* Now insert the match. */
12981acd27e7Smillert   if (replacement)
12991acd27e7Smillert     {
13001acd27e7Smillert       /* Don't double an opening quote character. */
13011acd27e7Smillert       if (qc && *qc && start && rl_line_buffer[start - 1] == *qc &&
13021acd27e7Smillert 	    replacement[0] == *qc)
13031acd27e7Smillert 	start--;
13041acd27e7Smillert       /* If make_quoted_replacement changed the quoting character, remove
13051acd27e7Smillert 	 the opening quote and insert the (fully-quoted) replacement. */
13061acd27e7Smillert       else if (qc && (*qc != oqc) && start && rl_line_buffer[start - 1] == oqc &&
13071acd27e7Smillert 	    replacement[0] != oqc)
13081acd27e7Smillert 	start--;
13091acd27e7Smillert       _rl_replace_text (replacement, start, rl_point - 1);
13101acd27e7Smillert       if (replacement != match)
13111acd27e7Smillert         free (replacement);
13121acd27e7Smillert     }
13131acd27e7Smillert }
13141acd27e7Smillert 
13151acd27e7Smillert /* Append any necessary closing quote and a separator character to the
13161acd27e7Smillert    just-inserted match.  If the user has specified that directories
13171acd27e7Smillert    should be marked by a trailing `/', append one of those instead.  The
13181acd27e7Smillert    default trailing character is a space.  Returns the number of characters
1319af70c2dfSkettenis    appended.  If NONTRIVIAL_MATCH is set, we test for a symlink (if the OS
1320af70c2dfSkettenis    has them) and don't add a suffix for a symlink to a directory.  A
1321af70c2dfSkettenis    nontrivial match is one that actually adds to the word being completed.
1322af70c2dfSkettenis    The variable rl_completion_mark_symlink_dirs controls this behavior
1323af70c2dfSkettenis    (it's initially set to the what the user has chosen, indicated by the
1324af70c2dfSkettenis    value of _rl_complete_mark_symlink_dirs, but may be modified by an
1325af70c2dfSkettenis    application's completion function). */
13261acd27e7Smillert static int
append_to_match(text,delimiter,quote_char,nontrivial_match)1327af70c2dfSkettenis append_to_match (text, delimiter, quote_char, nontrivial_match)
13281acd27e7Smillert      char *text;
1329af70c2dfSkettenis      int delimiter, quote_char, nontrivial_match;
13301acd27e7Smillert {
13311acd27e7Smillert   char temp_string[4], *filename;
1332af70c2dfSkettenis   int temp_string_index, s;
13331acd27e7Smillert   struct stat finfo;
13341acd27e7Smillert 
13351acd27e7Smillert   temp_string_index = 0;
13361acd27e7Smillert   if (quote_char && rl_point && rl_line_buffer[rl_point - 1] != quote_char)
13371acd27e7Smillert     temp_string[temp_string_index++] = quote_char;
13381acd27e7Smillert 
13391acd27e7Smillert   if (delimiter)
13401acd27e7Smillert     temp_string[temp_string_index++] = delimiter;
1341af70c2dfSkettenis   else if (rl_completion_suppress_append == 0 && rl_completion_append_character)
13421acd27e7Smillert     temp_string[temp_string_index++] = rl_completion_append_character;
13431acd27e7Smillert 
13441acd27e7Smillert   temp_string[temp_string_index++] = '\0';
13451acd27e7Smillert 
13461acd27e7Smillert   if (rl_filename_completion_desired)
13471acd27e7Smillert     {
13481acd27e7Smillert       filename = tilde_expand (text);
1349af70c2dfSkettenis       s = (nontrivial_match && rl_completion_mark_symlink_dirs == 0)
1350af70c2dfSkettenis 		? LSTAT (filename, &finfo)
1351af70c2dfSkettenis 		: stat (filename, &finfo);
1352af70c2dfSkettenis       if (s == 0 && S_ISDIR (finfo.st_mode))
13531acd27e7Smillert 	{
1354af70c2dfSkettenis 	  if (_rl_complete_mark_directories)
1355af70c2dfSkettenis 	    {
1356af70c2dfSkettenis 	      /* This is clumsy.  Avoid putting in a double slash if point
1357af70c2dfSkettenis 		 is at the end of the line and the previous character is a
1358af70c2dfSkettenis 		 slash. */
1359af70c2dfSkettenis 	      if (rl_point && rl_line_buffer[rl_point] == '\0' && rl_line_buffer[rl_point - 1] == '/')
1360af70c2dfSkettenis 		;
1361af70c2dfSkettenis 	      else if (rl_line_buffer[rl_point] != '/')
13621acd27e7Smillert 		rl_insert_text ("/");
13631acd27e7Smillert 	    }
1364af70c2dfSkettenis 	}
1365af70c2dfSkettenis #ifdef S_ISLNK
1366af70c2dfSkettenis       /* Don't add anything if the filename is a symlink and resolves to a
1367af70c2dfSkettenis 	 directory. */
1368af70c2dfSkettenis       else if (s == 0 && S_ISLNK (finfo.st_mode) &&
1369af70c2dfSkettenis 	       stat (filename, &finfo) == 0 && S_ISDIR (finfo.st_mode))
1370af70c2dfSkettenis 	;
1371af70c2dfSkettenis #endif
13721acd27e7Smillert       else
13731acd27e7Smillert 	{
1374af70c2dfSkettenis 	  if (rl_point == rl_end && temp_string_index)
13751acd27e7Smillert 	    rl_insert_text (temp_string);
13761acd27e7Smillert 	}
13771acd27e7Smillert       free (filename);
13781acd27e7Smillert     }
13791acd27e7Smillert   else
13801acd27e7Smillert     {
1381af70c2dfSkettenis       if (rl_point == rl_end && temp_string_index)
13821acd27e7Smillert 	rl_insert_text (temp_string);
13831acd27e7Smillert     }
13841acd27e7Smillert 
13851acd27e7Smillert   return (temp_string_index);
13861acd27e7Smillert }
13871acd27e7Smillert 
13881acd27e7Smillert static void
insert_all_matches(matches,point,qc)13891acd27e7Smillert insert_all_matches (matches, point, qc)
13901acd27e7Smillert      char **matches;
13911acd27e7Smillert      int point;
13921acd27e7Smillert      char *qc;
13931acd27e7Smillert {
13941acd27e7Smillert   int i;
13951acd27e7Smillert   char *rp;
13961acd27e7Smillert 
13971acd27e7Smillert   rl_begin_undo_group ();
13981acd27e7Smillert   /* remove any opening quote character; make_quoted_replacement will add
13991acd27e7Smillert      it back. */
14001acd27e7Smillert   if (qc && *qc && point && rl_line_buffer[point - 1] == *qc)
14011acd27e7Smillert     point--;
14021acd27e7Smillert   rl_delete_text (point, rl_point);
14031acd27e7Smillert   rl_point = point;
14041acd27e7Smillert 
14051acd27e7Smillert   if (matches[1])
14061acd27e7Smillert     {
14071acd27e7Smillert       for (i = 1; matches[i]; i++)
14081acd27e7Smillert 	{
14091acd27e7Smillert 	  rp = make_quoted_replacement (matches[i], SINGLE_MATCH, qc);
14101acd27e7Smillert 	  rl_insert_text (rp);
14111acd27e7Smillert 	  rl_insert_text (" ");
14121acd27e7Smillert 	  if (rp != matches[i])
14131acd27e7Smillert 	    free (rp);
14141acd27e7Smillert 	}
14151acd27e7Smillert     }
14161acd27e7Smillert   else
14171acd27e7Smillert     {
14181acd27e7Smillert       rp = make_quoted_replacement (matches[0], SINGLE_MATCH, qc);
14191acd27e7Smillert       rl_insert_text (rp);
14201acd27e7Smillert       rl_insert_text (" ");
14211acd27e7Smillert       if (rp != matches[0])
14221acd27e7Smillert 	free (rp);
14231acd27e7Smillert     }
14241acd27e7Smillert   rl_end_undo_group ();
14251acd27e7Smillert }
14261acd27e7Smillert 
1427af70c2dfSkettenis void
_rl_free_match_list(matches)1428af70c2dfSkettenis _rl_free_match_list (matches)
14291acd27e7Smillert      char **matches;
14301acd27e7Smillert {
14311acd27e7Smillert   register int i;
14321acd27e7Smillert 
1433af70c2dfSkettenis   if (matches == 0)
1434af70c2dfSkettenis     return;
1435af70c2dfSkettenis 
14361acd27e7Smillert   for (i = 0; matches[i]; i++)
14371acd27e7Smillert     free (matches[i]);
14381acd27e7Smillert   free (matches);
14391acd27e7Smillert }
14401acd27e7Smillert 
14411acd27e7Smillert /* Complete the word at or before point.
14421acd27e7Smillert    WHAT_TO_DO says what to do with the completion.
14431acd27e7Smillert    `?' means list the possible completions.
14441acd27e7Smillert    TAB means do standard completion.
14451acd27e7Smillert    `*' means insert all of the possible completions.
14461acd27e7Smillert    `!' means to do standard completion, and list all possible completions if
14471acd27e7Smillert    there is more than one. */
14481acd27e7Smillert int
rl_complete_internal(what_to_do)14491acd27e7Smillert rl_complete_internal (what_to_do)
14501acd27e7Smillert      int what_to_do;
14511acd27e7Smillert {
14521acd27e7Smillert   char **matches;
1453af70c2dfSkettenis   rl_compentry_func_t *our_func;
1454af70c2dfSkettenis   int start, end, delimiter, found_quote, i, nontrivial_lcd;
14551acd27e7Smillert   char *text, *saved_line_buffer;
14561acd27e7Smillert   char quote_char;
14571acd27e7Smillert 
1458af70c2dfSkettenis   RL_SETSTATE(RL_STATE_COMPLETING);
1459af70c2dfSkettenis 
1460af70c2dfSkettenis   set_completion_defaults (what_to_do);
14611acd27e7Smillert 
14621acd27e7Smillert   saved_line_buffer = rl_line_buffer ? savestring (rl_line_buffer) : (char *)NULL;
14631acd27e7Smillert   our_func = rl_completion_entry_function
14641acd27e7Smillert 		? rl_completion_entry_function
1465af70c2dfSkettenis 		: rl_filename_completion_function;
14661acd27e7Smillert 
14671acd27e7Smillert   /* We now look backwards for the start of a filename/variable word. */
14681acd27e7Smillert   end = rl_point;
14691acd27e7Smillert   found_quote = delimiter = 0;
14701acd27e7Smillert   quote_char = '\0';
14711acd27e7Smillert 
14721acd27e7Smillert   if (rl_point)
14731acd27e7Smillert     /* This (possibly) changes rl_point.  If it returns a non-zero char,
14741acd27e7Smillert        we know we have an open quote. */
1475af70c2dfSkettenis     quote_char = _rl_find_completion_word (&found_quote, &delimiter);
14761acd27e7Smillert 
14771acd27e7Smillert   start = rl_point;
14781acd27e7Smillert   rl_point = end;
14791acd27e7Smillert 
14801acd27e7Smillert   text = rl_copy_text (start, end);
14811acd27e7Smillert   matches = gen_completion_matches (text, start, end, our_func, found_quote, quote_char);
1482af70c2dfSkettenis   /* nontrivial_lcd is set if the common prefix adds something to the word
1483af70c2dfSkettenis      being completed. */
1484af70c2dfSkettenis   nontrivial_lcd = matches && strcmp (text, matches[0]) != 0;
14851acd27e7Smillert   free (text);
14861acd27e7Smillert 
14871acd27e7Smillert   if (matches == 0)
14881acd27e7Smillert     {
1489af70c2dfSkettenis       rl_ding ();
14901acd27e7Smillert       FREE (saved_line_buffer);
1491af70c2dfSkettenis       completion_changed_buffer = 0;
1492af70c2dfSkettenis       RL_UNSETSTATE(RL_STATE_COMPLETING);
14931acd27e7Smillert       return (0);
14941acd27e7Smillert     }
14951acd27e7Smillert 
14961acd27e7Smillert   /* If we are matching filenames, the attempted completion function will
14971acd27e7Smillert      have set rl_filename_completion_desired to a non-zero value.  The basic
1498af70c2dfSkettenis      rl_filename_completion_function does this. */
14991acd27e7Smillert   i = rl_filename_completion_desired;
15001acd27e7Smillert 
15011acd27e7Smillert   if (postprocess_matches (&matches, i) == 0)
15021acd27e7Smillert     {
1503af70c2dfSkettenis       rl_ding ();
15041acd27e7Smillert       FREE (saved_line_buffer);
15051acd27e7Smillert       completion_changed_buffer = 0;
1506af70c2dfSkettenis       RL_UNSETSTATE(RL_STATE_COMPLETING);
15071acd27e7Smillert       return (0);
15081acd27e7Smillert     }
15091acd27e7Smillert 
15101acd27e7Smillert   switch (what_to_do)
15111acd27e7Smillert     {
15121acd27e7Smillert     case TAB:
15131acd27e7Smillert     case '!':
15141acd27e7Smillert       /* Insert the first match with proper quoting. */
15151acd27e7Smillert       if (*matches[0])
15161acd27e7Smillert 	insert_match (matches[0], start, matches[1] ? MULT_MATCH : SINGLE_MATCH, &quote_char);
15171acd27e7Smillert 
15181acd27e7Smillert       /* If there are more matches, ring the bell to indicate.
15191acd27e7Smillert 	 If we are in vi mode, Posix.2 says to not ring the bell.
15201acd27e7Smillert 	 If the `show-all-if-ambiguous' variable is set, display
15211acd27e7Smillert 	 all the matches immediately.  Otherwise, if this was the
15221acd27e7Smillert 	 only match, and we are hacking files, check the file to
15231acd27e7Smillert 	 see if it was a directory.  If so, and the `mark-directories'
15241acd27e7Smillert 	 variable is set, add a '/' to the name.  If not, and we
15251acd27e7Smillert 	 are at the end of the line, then add a space.  */
15261acd27e7Smillert       if (matches[1])
15271acd27e7Smillert 	{
15281acd27e7Smillert 	  if (what_to_do == '!')
15291acd27e7Smillert 	    {
15301acd27e7Smillert 	      display_matches (matches);
15311acd27e7Smillert 	      break;
15321acd27e7Smillert 	    }
15331acd27e7Smillert 	  else if (rl_editing_mode != vi_mode)
1534af70c2dfSkettenis 	    rl_ding ();	/* There are other matches remaining. */
15351acd27e7Smillert 	}
15361acd27e7Smillert       else
1537af70c2dfSkettenis 	append_to_match (matches[0], delimiter, quote_char, nontrivial_lcd);
15381acd27e7Smillert 
15391acd27e7Smillert       break;
15401acd27e7Smillert 
15411acd27e7Smillert     case '*':
15421acd27e7Smillert       insert_all_matches (matches, start, &quote_char);
15431acd27e7Smillert       break;
15441acd27e7Smillert 
15451acd27e7Smillert     case '?':
15461acd27e7Smillert       display_matches (matches);
15471acd27e7Smillert       break;
15481acd27e7Smillert 
15491acd27e7Smillert     default:
15501acd27e7Smillert       fprintf (stderr, "\r\nreadline: bad value %d for what_to_do in rl_complete\n", what_to_do);
1551af70c2dfSkettenis       rl_ding ();
15521acd27e7Smillert       FREE (saved_line_buffer);
1553af70c2dfSkettenis       RL_UNSETSTATE(RL_STATE_COMPLETING);
15541acd27e7Smillert       return 1;
15551acd27e7Smillert     }
15561acd27e7Smillert 
1557af70c2dfSkettenis   _rl_free_match_list (matches);
15581acd27e7Smillert 
15591acd27e7Smillert   /* Check to see if the line has changed through all of this manipulation. */
15601acd27e7Smillert   if (saved_line_buffer)
15611acd27e7Smillert     {
15621acd27e7Smillert       completion_changed_buffer = strcmp (rl_line_buffer, saved_line_buffer) != 0;
15631acd27e7Smillert       free (saved_line_buffer);
15641acd27e7Smillert     }
15651acd27e7Smillert 
1566af70c2dfSkettenis   RL_UNSETSTATE(RL_STATE_COMPLETING);
15671acd27e7Smillert   return 0;
15681acd27e7Smillert }
15691acd27e7Smillert 
15701acd27e7Smillert /***************************************************************/
15711acd27e7Smillert /*							       */
15721acd27e7Smillert /*  Application-callable completion match generator functions  */
15731acd27e7Smillert /*							       */
15741acd27e7Smillert /***************************************************************/
15751acd27e7Smillert 
15761acd27e7Smillert /* Return an array of (char *) which is a list of completions for TEXT.
15771acd27e7Smillert    If there are no completions, return a NULL pointer.
15781acd27e7Smillert    The first entry in the returned array is the substitution for TEXT.
15791acd27e7Smillert    The remaining entries are the possible completions.
15801acd27e7Smillert    The array is terminated with a NULL pointer.
15811acd27e7Smillert 
15821acd27e7Smillert    ENTRY_FUNCTION is a function of two args, and returns a (char *).
15831acd27e7Smillert      The first argument is TEXT.
15841acd27e7Smillert      The second is a state argument; it should be zero on the first call, and
15851acd27e7Smillert      non-zero on subsequent calls.  It returns a NULL pointer to the caller
15861acd27e7Smillert      when there are no more matches.
15871acd27e7Smillert  */
15881acd27e7Smillert char **
rl_completion_matches(text,entry_function)1589af70c2dfSkettenis rl_completion_matches (text, entry_function)
1590af70c2dfSkettenis      const char *text;
1591af70c2dfSkettenis      rl_compentry_func_t *entry_function;
15921acd27e7Smillert {
15931acd27e7Smillert   /* Number of slots in match_list. */
15941acd27e7Smillert   int match_list_size;
15951acd27e7Smillert 
15961acd27e7Smillert   /* The list of matches. */
15971acd27e7Smillert   char **match_list;
15981acd27e7Smillert 
15991acd27e7Smillert   /* Number of matches actually found. */
16001acd27e7Smillert   int matches;
16011acd27e7Smillert 
16021acd27e7Smillert   /* Temporary string binder. */
16031acd27e7Smillert   char *string;
16041acd27e7Smillert 
16051acd27e7Smillert   matches = 0;
16061acd27e7Smillert   match_list_size = 10;
16071acd27e7Smillert   match_list = (char **)xmalloc ((match_list_size + 1) * sizeof (char *));
16081acd27e7Smillert   match_list[1] = (char *)NULL;
16091acd27e7Smillert 
1610*af1e7b8cSkrw   while ((string = (*entry_function) (text, matches)))
16111acd27e7Smillert     {
16121acd27e7Smillert       if (matches + 1 == match_list_size)
16131acd27e7Smillert 	match_list = (char **)xrealloc
16141acd27e7Smillert 	  (match_list, ((match_list_size += 10) + 1) * sizeof (char *));
16151acd27e7Smillert 
16161acd27e7Smillert       match_list[++matches] = string;
16171acd27e7Smillert       match_list[matches + 1] = (char *)NULL;
16181acd27e7Smillert     }
16191acd27e7Smillert 
16201acd27e7Smillert   /* If there were any matches, then look through them finding out the
16211acd27e7Smillert      lowest common denominator.  That then becomes match_list[0]. */
16221acd27e7Smillert   if (matches)
16231acd27e7Smillert     compute_lcd_of_matches (match_list, matches, text);
16241acd27e7Smillert   else				/* There were no matches. */
16251acd27e7Smillert     {
16261acd27e7Smillert       free (match_list);
16271acd27e7Smillert       match_list = (char **)NULL;
16281acd27e7Smillert     }
16291acd27e7Smillert   return (match_list);
16301acd27e7Smillert }
16311acd27e7Smillert 
16321acd27e7Smillert /* A completion function for usernames.
16331acd27e7Smillert    TEXT contains a partial username preceded by a random
16341acd27e7Smillert    character (usually `~').  */
16351acd27e7Smillert char *
rl_username_completion_function(text,state)1636af70c2dfSkettenis rl_username_completion_function (text, state)
1637af70c2dfSkettenis      const char *text;
16381acd27e7Smillert      int state;
16391acd27e7Smillert {
16401acd27e7Smillert #if defined (__WIN32__) || defined (__OPENNT)
16411acd27e7Smillert   return (char *)NULL;
16421acd27e7Smillert #else /* !__WIN32__ && !__OPENNT) */
16431acd27e7Smillert   static char *username = (char *)NULL;
16441acd27e7Smillert   static struct passwd *entry;
16451acd27e7Smillert   static int namelen, first_char, first_char_loc;
16461acd27e7Smillert   char *value;
16471acd27e7Smillert 
16481acd27e7Smillert   if (state == 0)
16491acd27e7Smillert     {
16501acd27e7Smillert       FREE (username);
16511acd27e7Smillert 
16521acd27e7Smillert       first_char = *text;
16531acd27e7Smillert       first_char_loc = first_char == '~';
16541acd27e7Smillert 
16551acd27e7Smillert       username = savestring (&text[first_char_loc]);
16561acd27e7Smillert       namelen = strlen (username);
16571acd27e7Smillert       setpwent ();
16581acd27e7Smillert     }
16591acd27e7Smillert 
1660*af1e7b8cSkrw   while ((entry = getpwent ()))
16611acd27e7Smillert     {
16621acd27e7Smillert       /* Null usernames should result in all users as possible completions. */
16631acd27e7Smillert       if (namelen == 0 || (STREQN (username, entry->pw_name, namelen)))
16641acd27e7Smillert 	break;
16651acd27e7Smillert     }
16661acd27e7Smillert 
16671acd27e7Smillert   if (entry == 0)
16681acd27e7Smillert     {
16691acd27e7Smillert       endpwent ();
16701acd27e7Smillert       return ((char *)NULL);
16711acd27e7Smillert     }
16721acd27e7Smillert   else
16731acd27e7Smillert     {
167463bef317Sbeck       int len = 2 + strlen(entry->pw_name);
1675af70c2dfSkettenis       value = (char *)xmalloc (len);
16761acd27e7Smillert 
16771acd27e7Smillert       *value = *text;
16781acd27e7Smillert 
167963bef317Sbeck       strlcpy (value + first_char_loc, entry->pw_name, len - first_char_loc);
16801acd27e7Smillert 
16811acd27e7Smillert       if (first_char == '~')
16821acd27e7Smillert 	rl_filename_completion_desired = 1;
16831acd27e7Smillert 
16841acd27e7Smillert       return (value);
16851acd27e7Smillert     }
16861acd27e7Smillert #endif /* !__WIN32__ && !__OPENNT */
16871acd27e7Smillert }
16881acd27e7Smillert 
16891acd27e7Smillert /* Okay, now we write the entry_function for filename completion.  In the
16901acd27e7Smillert    general case.  Note that completion in the shell is a little different
16911acd27e7Smillert    because of all the pathnames that must be followed when looking up the
16921acd27e7Smillert    completion for a command. */
16931acd27e7Smillert char *
rl_filename_completion_function(text,state)1694af70c2dfSkettenis rl_filename_completion_function (text, state)
1695af70c2dfSkettenis      const char *text;
16961acd27e7Smillert      int state;
16971acd27e7Smillert {
16981acd27e7Smillert   static DIR *directory = (DIR *)NULL;
16991acd27e7Smillert   static char *filename = (char *)NULL;
17001acd27e7Smillert   static char *dirname = (char *)NULL;
17011acd27e7Smillert   static char *users_dirname = (char *)NULL;
17021acd27e7Smillert   static int filename_len;
17031acd27e7Smillert   char *temp;
17041acd27e7Smillert   int dirlen;
17051acd27e7Smillert   struct dirent *entry;
17061acd27e7Smillert 
17071acd27e7Smillert   /* If we don't have any state, then do some initialization. */
17081acd27e7Smillert   if (state == 0)
17091acd27e7Smillert     {
17101acd27e7Smillert       /* If we were interrupted before closing the directory or reading
17111acd27e7Smillert 	 all of its contents, close it. */
17121acd27e7Smillert       if (directory)
17131acd27e7Smillert 	{
17141acd27e7Smillert 	  closedir (directory);
17151acd27e7Smillert 	  directory = (DIR *)NULL;
17161acd27e7Smillert 	}
17171acd27e7Smillert       FREE (dirname);
17181acd27e7Smillert       FREE (filename);
17191acd27e7Smillert       FREE (users_dirname);
17201acd27e7Smillert 
17211acd27e7Smillert       filename = savestring (text);
172200d4b8aeStedu       filename_len = strlen(filename) + 1;
17231acd27e7Smillert       if (*text == 0)
17241acd27e7Smillert 	text = ".";
17251acd27e7Smillert       dirname = savestring (text);
17261acd27e7Smillert 
17271acd27e7Smillert       temp = strrchr (dirname, '/');
17281acd27e7Smillert 
17291acd27e7Smillert #if defined (__MSDOS__)
17301acd27e7Smillert       /* special hack for //X/... */
1731af70c2dfSkettenis       if (dirname[0] == '/' && dirname[1] == '/' && ISALPHA ((unsigned char)dirname[2]) && dirname[3] == '/')
17321acd27e7Smillert         temp = strrchr (dirname + 3, '/');
17331acd27e7Smillert #endif
17341acd27e7Smillert 
17351acd27e7Smillert       if (temp)
17361acd27e7Smillert 	{
173763bef317Sbeck 	  strlcpy (filename, ++temp, filename_len);
17381acd27e7Smillert 	  *temp = '\0';
17391acd27e7Smillert 	}
17401acd27e7Smillert #if defined (__MSDOS__)
17411acd27e7Smillert       /* searches from current directory on the drive */
1742af70c2dfSkettenis       else if (ISALPHA ((unsigned char)dirname[0]) && dirname[1] == ':')
17431acd27e7Smillert         {
174463bef317Sbeck 	  /* XXX DOS strlcpy anyone? */
174563bef317Sbeck           strlcpy (filename, dirname + 2, filename_len);
17461acd27e7Smillert           dirname[2] = '\0';
17471acd27e7Smillert         }
17481acd27e7Smillert #endif
17491acd27e7Smillert       else
17501acd27e7Smillert 	{
17511acd27e7Smillert 	  dirname[0] = '.';
17521acd27e7Smillert 	  dirname[1] = '\0';
17531acd27e7Smillert 	}
17541acd27e7Smillert 
17551acd27e7Smillert       /* We aren't done yet.  We also support the "~user" syntax. */
17561acd27e7Smillert 
17571acd27e7Smillert       /* Save the version of the directory that the user typed. */
17581acd27e7Smillert       users_dirname = savestring (dirname);
17591acd27e7Smillert 
17601acd27e7Smillert       if (*dirname == '~')
17611acd27e7Smillert 	{
17621acd27e7Smillert 	  temp = tilde_expand (dirname);
17631acd27e7Smillert 	  free (dirname);
17641acd27e7Smillert 	  dirname = temp;
17651acd27e7Smillert 	}
17661acd27e7Smillert 
1767af70c2dfSkettenis       if (rl_directory_rewrite_hook)
1768af70c2dfSkettenis 	(*rl_directory_rewrite_hook) (&dirname);
1769af70c2dfSkettenis 
17701acd27e7Smillert       if (rl_directory_completion_hook && (*rl_directory_completion_hook) (&dirname))
17711acd27e7Smillert 	{
17721acd27e7Smillert 	  free (users_dirname);
17731acd27e7Smillert 	  users_dirname = savestring (dirname);
17741acd27e7Smillert 	}
17751acd27e7Smillert 
17761acd27e7Smillert       directory = opendir (dirname);
17771acd27e7Smillert       filename_len = strlen (filename);
17781acd27e7Smillert 
17791acd27e7Smillert       rl_filename_completion_desired = 1;
17801acd27e7Smillert     }
17811acd27e7Smillert 
17821acd27e7Smillert   /* At this point we should entertain the possibility of hacking wildcarded
17831acd27e7Smillert      filenames, like /usr/man/man<WILD>/te<TAB>.  If the directory name
17841acd27e7Smillert      contains globbing characters, then build an array of directories, and
17851acd27e7Smillert      then map over that list while completing. */
17861acd27e7Smillert   /* *** UNIMPLEMENTED *** */
17871acd27e7Smillert 
17881acd27e7Smillert   /* Now that we have some state, we can read the directory. */
17891acd27e7Smillert 
17901acd27e7Smillert   entry = (struct dirent *)NULL;
17911acd27e7Smillert   while (directory && (entry = readdir (directory)))
17921acd27e7Smillert     {
1793af70c2dfSkettenis       /* Special case for no filename.  If the user has disabled the
1794af70c2dfSkettenis          `match-hidden-files' variable, skip filenames beginning with `.'.
1795af70c2dfSkettenis 	 All other entries except "." and ".." match. */
17961acd27e7Smillert       if (filename_len == 0)
17971acd27e7Smillert 	{
1798af70c2dfSkettenis 	  if (_rl_match_hidden_files == 0 && HIDDEN_FILE (entry->d_name))
1799af70c2dfSkettenis 	    continue;
1800af70c2dfSkettenis 
18011acd27e7Smillert 	  if (entry->d_name[0] != '.' ||
18021acd27e7Smillert 	       (entry->d_name[1] &&
18031acd27e7Smillert 		 (entry->d_name[1] != '.' || entry->d_name[2])))
18041acd27e7Smillert 	    break;
18051acd27e7Smillert 	}
18061acd27e7Smillert       else
18071acd27e7Smillert 	{
18081acd27e7Smillert 	  /* Otherwise, if these match up to the length of filename, then
18091acd27e7Smillert 	     it is a match. */
18101acd27e7Smillert 	  if (_rl_completion_case_fold)
18111acd27e7Smillert 	    {
18121acd27e7Smillert 	      if ((_rl_to_lower (entry->d_name[0]) == _rl_to_lower (filename[0])) &&
18131acd27e7Smillert 		  (((int)D_NAMLEN (entry)) >= filename_len) &&
18141acd27e7Smillert 		  (_rl_strnicmp (filename, entry->d_name, filename_len) == 0))
18151acd27e7Smillert 		break;
18161acd27e7Smillert 	    }
18171acd27e7Smillert 	  else
18181acd27e7Smillert 	    {
18191acd27e7Smillert 	      if ((entry->d_name[0] == filename[0]) &&
18201acd27e7Smillert 		  (((int)D_NAMLEN (entry)) >= filename_len) &&
18211acd27e7Smillert 		  (strncmp (filename, entry->d_name, filename_len) == 0))
18221acd27e7Smillert 		break;
18231acd27e7Smillert 	    }
18241acd27e7Smillert 	}
18251acd27e7Smillert     }
18261acd27e7Smillert 
18271acd27e7Smillert   if (entry == 0)
18281acd27e7Smillert     {
18291acd27e7Smillert       if (directory)
18301acd27e7Smillert 	{
18311acd27e7Smillert 	  closedir (directory);
18321acd27e7Smillert 	  directory = (DIR *)NULL;
18331acd27e7Smillert 	}
18341acd27e7Smillert       if (dirname)
18351acd27e7Smillert 	{
18361acd27e7Smillert 	  free (dirname);
18371acd27e7Smillert 	  dirname = (char *)NULL;
18381acd27e7Smillert 	}
18391acd27e7Smillert       if (filename)
18401acd27e7Smillert 	{
18411acd27e7Smillert 	  free (filename);
18421acd27e7Smillert 	  filename = (char *)NULL;
18431acd27e7Smillert 	}
18441acd27e7Smillert       if (users_dirname)
18451acd27e7Smillert 	{
18461acd27e7Smillert 	  free (users_dirname);
18471acd27e7Smillert 	  users_dirname = (char *)NULL;
18481acd27e7Smillert 	}
18491acd27e7Smillert 
18501acd27e7Smillert       return (char *)NULL;
18511acd27e7Smillert     }
18521acd27e7Smillert   else
18531acd27e7Smillert     {
18541acd27e7Smillert       /* dirname && (strcmp (dirname, ".") != 0) */
18551acd27e7Smillert       if (dirname && (dirname[0] != '.' || dirname[1]))
18561acd27e7Smillert 	{
185763bef317Sbeck 	  int templen;
18581acd27e7Smillert 	  if (rl_complete_with_tilde_expansion && *users_dirname == '~')
18591acd27e7Smillert 	    {
18601acd27e7Smillert 	      dirlen = strlen (dirname);
186163bef317Sbeck 	      templen = 2 + dirlen + D_NAMLEN (entry);
1862af70c2dfSkettenis 	      temp = (char *)xmalloc (templen);
186363bef317Sbeck 	      strlcpy (temp, dirname, templen);
18641acd27e7Smillert 	      /* Canonicalization cuts off any final slash present.  We
18651acd27e7Smillert 		 may need to add it back. */
18661acd27e7Smillert 	      if (dirname[dirlen - 1] != '/')
18671acd27e7Smillert 	        {
18681acd27e7Smillert 	          temp[dirlen++] = '/';
18691acd27e7Smillert 	          temp[dirlen] = '\0';
18701acd27e7Smillert 	        }
18711acd27e7Smillert 	    }
18721acd27e7Smillert 	  else
18731acd27e7Smillert 	    {
18741acd27e7Smillert 	      dirlen = strlen (users_dirname);
1875af70c2dfSkettenis 	      templen = 2 + dirlen + D_NAMLEN (entry);
1876af70c2dfSkettenis 	      temp = (char *)xmalloc (templen);
187763bef317Sbeck 	      strlcpy (temp, users_dirname, templen);
1878af70c2dfSkettenis 	      /* Make sure that temp has a trailing slash here. */
1879af70c2dfSkettenis 	      if (users_dirname[dirlen - 1] != '/')
1880af70c2dfSkettenis 	        {
1881af70c2dfSkettenis 		  temp[dirlen++] = '/';
1882af70c2dfSkettenis 	          temp[dirlen] = '\0';
1883af70c2dfSkettenis 	        }
18841acd27e7Smillert 	    }
18851acd27e7Smillert 
188663bef317Sbeck 	  strlcat (temp, entry->d_name, templen);
18871acd27e7Smillert 	}
18881acd27e7Smillert       else
18891acd27e7Smillert 	temp = savestring (entry->d_name);
18901acd27e7Smillert 
18911acd27e7Smillert       return (temp);
18921acd27e7Smillert     }
18931acd27e7Smillert }
18941acd27e7Smillert 
18951acd27e7Smillert /* An initial implementation of a menu completion function a la tcsh.  The
18961acd27e7Smillert    first time (if the last readline command was not rl_menu_complete), we
18971acd27e7Smillert    generate the list of matches.  This code is very similar to the code in
18981acd27e7Smillert    rl_complete_internal -- there should be a way to combine the two.  Then,
18991acd27e7Smillert    for each item in the list of matches, we insert the match in an undoable
19001acd27e7Smillert    fashion, with the appropriate character appended (this happens on the
19011acd27e7Smillert    second and subsequent consecutive calls to rl_menu_complete).  When we
19021acd27e7Smillert    hit the end of the match list, we restore the original unmatched text,
19031acd27e7Smillert    ring the bell, and reset the counter to zero. */
19041acd27e7Smillert int
rl_menu_complete(count,ignore)19051acd27e7Smillert rl_menu_complete (count, ignore)
19061acd27e7Smillert      int count, ignore;
19071acd27e7Smillert {
1908af70c2dfSkettenis   rl_compentry_func_t *our_func;
19091acd27e7Smillert   int matching_filenames, found_quote;
19101acd27e7Smillert 
19111acd27e7Smillert   static char *orig_text;
19121acd27e7Smillert   static char **matches = (char **)0;
19131acd27e7Smillert   static int match_list_index = 0;
19141acd27e7Smillert   static int match_list_size = 0;
19151acd27e7Smillert   static int orig_start, orig_end;
19161acd27e7Smillert   static char quote_char;
19171acd27e7Smillert   static int delimiter;
19181acd27e7Smillert 
19191acd27e7Smillert   /* The first time through, we generate the list of matches and set things
19201acd27e7Smillert      up to insert them. */
19211acd27e7Smillert   if (rl_last_func != rl_menu_complete)
19221acd27e7Smillert     {
19231acd27e7Smillert       /* Clean up from previous call, if any. */
19241acd27e7Smillert       FREE (orig_text);
19251acd27e7Smillert       if (matches)
1926af70c2dfSkettenis 	_rl_free_match_list (matches);
19271acd27e7Smillert 
19281acd27e7Smillert       match_list_index = match_list_size = 0;
19291acd27e7Smillert       matches = (char **)NULL;
19301acd27e7Smillert 
19311acd27e7Smillert       /* Only the completion entry function can change these. */
1932af70c2dfSkettenis       set_completion_defaults ('%');
19331acd27e7Smillert 
19341acd27e7Smillert       our_func = rl_completion_entry_function
19351acd27e7Smillert 			? rl_completion_entry_function
1936af70c2dfSkettenis 			: rl_filename_completion_function;
19371acd27e7Smillert 
19381acd27e7Smillert       /* We now look backwards for the start of a filename/variable word. */
19391acd27e7Smillert       orig_end = rl_point;
19401acd27e7Smillert       found_quote = delimiter = 0;
19411acd27e7Smillert       quote_char = '\0';
19421acd27e7Smillert 
19431acd27e7Smillert       if (rl_point)
19441acd27e7Smillert 	/* This (possibly) changes rl_point.  If it returns a non-zero char,
19451acd27e7Smillert 	   we know we have an open quote. */
1946af70c2dfSkettenis 	quote_char = _rl_find_completion_word (&found_quote, &delimiter);
19471acd27e7Smillert 
19481acd27e7Smillert       orig_start = rl_point;
19491acd27e7Smillert       rl_point = orig_end;
19501acd27e7Smillert 
19511acd27e7Smillert       orig_text = rl_copy_text (orig_start, orig_end);
19521acd27e7Smillert       matches = gen_completion_matches (orig_text, orig_start, orig_end,
19531acd27e7Smillert 					our_func, found_quote, quote_char);
19541acd27e7Smillert 
19551acd27e7Smillert       /* If we are matching filenames, the attempted completion function will
19561acd27e7Smillert 	 have set rl_filename_completion_desired to a non-zero value.  The basic
1957af70c2dfSkettenis 	 rl_filename_completion_function does this. */
19581acd27e7Smillert       matching_filenames = rl_filename_completion_desired;
1959af70c2dfSkettenis 
19601acd27e7Smillert       if (matches == 0 || postprocess_matches (&matches, matching_filenames) == 0)
19611acd27e7Smillert 	{
1962af70c2dfSkettenis 	  rl_ding ();
19631acd27e7Smillert 	  FREE (matches);
19641acd27e7Smillert 	  matches = (char **)0;
19651acd27e7Smillert 	  FREE (orig_text);
19661acd27e7Smillert 	  orig_text = (char *)0;
19671acd27e7Smillert 	  completion_changed_buffer = 0;
19681acd27e7Smillert           return (0);
19691acd27e7Smillert 	}
19701acd27e7Smillert 
19711acd27e7Smillert       for (match_list_size = 0; matches[match_list_size]; match_list_size++)
19721acd27e7Smillert         ;
19731acd27e7Smillert       /* matches[0] is lcd if match_list_size > 1, but the circular buffer
19741acd27e7Smillert 	 code below should take care of it. */
19751acd27e7Smillert     }
19761acd27e7Smillert 
19771acd27e7Smillert   /* Now we have the list of matches.  Replace the text between
19781acd27e7Smillert      rl_line_buffer[orig_start] and rl_line_buffer[rl_point] with
19791acd27e7Smillert      matches[match_list_index], and add any necessary closing char. */
19801acd27e7Smillert 
19811acd27e7Smillert   if (matches == 0 || match_list_size == 0)
19821acd27e7Smillert     {
1983af70c2dfSkettenis       rl_ding ();
19841acd27e7Smillert       FREE (matches);
19851acd27e7Smillert       matches = (char **)0;
19861acd27e7Smillert       completion_changed_buffer = 0;
19871acd27e7Smillert       return (0);
19881acd27e7Smillert     }
19891acd27e7Smillert 
19901acd27e7Smillert   match_list_index = (match_list_index + count) % match_list_size;
19911acd27e7Smillert   if (match_list_index < 0)
19921acd27e7Smillert     match_list_index += match_list_size;
19931acd27e7Smillert 
19941acd27e7Smillert   if (match_list_index == 0 && match_list_size > 1)
19951acd27e7Smillert     {
1996af70c2dfSkettenis       rl_ding ();
19971acd27e7Smillert       insert_match (orig_text, orig_start, MULT_MATCH, &quote_char);
19981acd27e7Smillert     }
19991acd27e7Smillert   else
20001acd27e7Smillert     {
20011acd27e7Smillert       insert_match (matches[match_list_index], orig_start, SINGLE_MATCH, &quote_char);
2002af70c2dfSkettenis       append_to_match (matches[match_list_index], delimiter, quote_char,
2003af70c2dfSkettenis 		       strcmp (orig_text, matches[match_list_index]));
20041acd27e7Smillert     }
20051acd27e7Smillert 
20061acd27e7Smillert   completion_changed_buffer = 1;
20071acd27e7Smillert   return (0);
20081acd27e7Smillert }
2009