| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | /* complete.c -- filename completion for readline. */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | /* Copyright (C) 1987-2009 Free Software Foundation, Inc.
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |    This file is part of the GNU Readline Library (Readline), a library | 
					
						
							|  |  |  |    for reading lines of text with interactive input and history editing. | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |    Readline is free software: you can redistribute it and/or modify | 
					
						
							|  |  |  |    it under the terms of the GNU General Public License as published by | 
					
						
							|  |  |  |    the Free Software Foundation, either version 3 of the License, or | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |    (at your option) any later version. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |    Readline is distributed in the hope that it will be useful, | 
					
						
							|  |  |  |    but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  |    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |    GNU General Public License for more details. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |    You should have received a copy of the GNU General Public License | 
					
						
							|  |  |  |    along with Readline.  If not, see <http://www.gnu.org/licenses/>.
 | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | #define READLINE_LIBRARY
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined (HAVE_CONFIG_H)
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | #  include <config.h>
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <sys/types.h>
 | 
					
						
							|  |  |  | #include <fcntl.h>
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | #if defined (HAVE_SYS_FILE_H)
 | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | #  include <sys/file.h>
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #if defined (HAVE_UNISTD_H)
 | 
					
						
							|  |  |  | #  include <unistd.h>
 | 
					
						
							|  |  |  | #endif /* HAVE_UNISTD_H */
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined (HAVE_STDLIB_H)
 | 
					
						
							|  |  |  | #  include <stdlib.h>
 | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | #  include "ansi_stdlib.h"
 | 
					
						
							|  |  |  | #endif /* HAVE_STDLIB_H */
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  | #include <stdio.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | #include <errno.h>
 | 
					
						
							|  |  |  | #if !defined (errno)
 | 
					
						
							|  |  |  | extern int errno; | 
					
						
							|  |  |  | #endif /* !errno */
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  | #if defined (HAVE_PWD_H)
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | #include <pwd.h>
 | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | #include "posixdir.h"
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | #include "posixstat.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* System-specific feature definitions and include files. */ | 
					
						
							|  |  |  | #include "rldefs.h"
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | #include "rlmbutil.h"
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* Some standard library routines. */ | 
					
						
							|  |  |  | #include "readline.h"
 | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | #include "xmalloc.h"
 | 
					
						
							|  |  |  | #include "rlprivate.h"
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | #ifdef __STDC__
 | 
					
						
							|  |  |  | typedef int QSFUNC (const void *, const void *); | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | typedef int QSFUNC (); | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | #ifdef HAVE_LSTAT
 | 
					
						
							|  |  |  | #  define LSTAT lstat
 | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | #  define LSTAT stat
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Unix version of a hidden file.  Could be different on other systems. */ | 
					
						
							|  |  |  | #define HIDDEN_FILE(fname)	((fname)[0] == '.')
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | /* Most systems don't declare getpwent in <pwd.h> if _POSIX_SOURCE is
 | 
					
						
							|  |  |  |    defined. */ | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  | #if defined (HAVE_GETPWENT) && (!defined (HAVE_GETPW_DECLS) || defined (_POSIX_SOURCE))
 | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | extern struct passwd *getpwent PARAMS((void)); | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  | #endif /* HAVE_GETPWENT && (!HAVE_GETPW_DECLS || _POSIX_SOURCE) */
 | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-02-19 17:11:39 +00:00
										 |  |  | /* If non-zero, then this is the address of a function to call when
 | 
					
						
							|  |  |  |    completing a word would normally display the list of possible matches. | 
					
						
							|  |  |  |    This function is called instead of actually doing the display. | 
					
						
							|  |  |  |    It takes three arguments: (char **matches, int num_matches, int max_length) | 
					
						
							|  |  |  |    where MATCHES is the array of strings that matched, NUM_MATCHES is the | 
					
						
							|  |  |  |    number of strings in that array, and MAX_LENGTH is the length of the | 
					
						
							|  |  |  |    longest string in that array. */ | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | rl_compdisp_func_t *rl_completion_display_matches_hook = (rl_compdisp_func_t *)NULL; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | #if defined (VISIBLE_STATS)
 | 
					
						
							|  |  |  | #  if !defined (X_OK)
 | 
					
						
							|  |  |  | #    define X_OK 1
 | 
					
						
							|  |  |  | #  endif
 | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | static int stat_char PARAMS((char *)); | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | static int path_isdir PARAMS((const char *)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | static char *rl_quote_filename PARAMS((char *, int, char *)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | static void set_completion_defaults PARAMS((int)); | 
					
						
							|  |  |  | static int get_y_or_n PARAMS((int)); | 
					
						
							|  |  |  | static int _rl_internal_pager PARAMS((int)); | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | static char *printable_part PARAMS((char *)); | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | static int fnwidth PARAMS((const char *)); | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | static int fnprint PARAMS((const char *, int)); | 
					
						
							|  |  |  | static int print_filename PARAMS((char *, char *, int)); | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | static char **gen_completion_matches PARAMS((char *, int, int, rl_compentry_func_t *, int, int)); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | static char **remove_duplicate_matches PARAMS((char **)); | 
					
						
							|  |  |  | static void insert_match PARAMS((char *, int, int, char *)); | 
					
						
							|  |  |  | static int append_to_match PARAMS((char *, int, int, int)); | 
					
						
							|  |  |  | static void insert_all_matches PARAMS((char **, int, char *)); | 
					
						
							|  |  |  | static void display_matches PARAMS((char **)); | 
					
						
							|  |  |  | static int compute_lcd_of_matches PARAMS((char **, int, const char *)); | 
					
						
							|  |  |  | static int postprocess_matches PARAMS((char ***, int)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static char *make_quoted_replacement PARAMS((char *, int, char *)); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | /* **************************************************************** */ | 
					
						
							|  |  |  | /*								    */ | 
					
						
							|  |  |  | /*	Completion matching, from readline's point of view.	    */ | 
					
						
							|  |  |  | /*								    */ | 
					
						
							|  |  |  | /* **************************************************************** */ | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | /* Variables known only to the readline library. */ | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* If non-zero, non-unique completions always show the list of matches. */ | 
					
						
							|  |  |  | int _rl_complete_show_all = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | /* If non-zero, non-unique completions show the list of matches, unless it
 | 
					
						
							|  |  |  |    is not possible to do partial completion and modify the line. */ | 
					
						
							|  |  |  | int _rl_complete_show_unmodified = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | /* If non-zero, completed directory names have a slash appended. */ | 
					
						
							|  |  |  | int _rl_complete_mark_directories = 1; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | /* If non-zero, the symlinked directory completion behavior introduced in
 | 
					
						
							|  |  |  |    readline-4.2a is disabled, and symlinks that point to directories have | 
					
						
							|  |  |  |    a slash appended (subject to the value of _rl_complete_mark_directories). | 
					
						
							|  |  |  |    This is user-settable via the mark-symlinked-directories variable. */ | 
					
						
							|  |  |  | int _rl_complete_mark_symlink_dirs = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | /* If non-zero, completions are printed horizontally in alphabetical order,
 | 
					
						
							|  |  |  |    like `ls -x'. */ | 
					
						
							|  |  |  | int _rl_print_completions_horizontally; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | /* Non-zero means that case is not significant in filename completion. */ | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | #if defined (__MSDOS__) && !defined (__DJGPP__)
 | 
					
						
							|  |  |  | int _rl_completion_case_fold = 1; | 
					
						
							|  |  |  | #else
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | int _rl_completion_case_fold; | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | /* If non-zero, don't match hidden files (filenames beginning with a `.' on
 | 
					
						
							|  |  |  |    Unix) when doing filename completion. */ | 
					
						
							|  |  |  | int _rl_match_hidden_files = 1; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | /* Length in characters of a common prefix replaced with an ellipsis (`...')
 | 
					
						
							|  |  |  |    when displaying completion matches.  Matches whose printable portion has | 
					
						
							|  |  |  |    more than this number of displaying characters in common will have the common | 
					
						
							|  |  |  |    display prefix replaced with an ellipsis. */ | 
					
						
							|  |  |  | int _rl_completion_prefix_display_length = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | /* Global variables available to applications using readline. */ | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | #if defined (VISIBLE_STATS)
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | /* Non-zero means add an additional character to each filename displayed
 | 
					
						
							|  |  |  |    during listing completion iff rl_filename_completion_desired which helps | 
					
						
							|  |  |  |    to indicate the type of file being listed. */ | 
					
						
							|  |  |  | int rl_visible_stats = 0; | 
					
						
							|  |  |  | #endif /* VISIBLE_STATS */
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | /* If non-zero, then this is the address of a function to call when
 | 
					
						
							|  |  |  |    completing on a directory name.  The function is called with | 
					
						
							|  |  |  |    the address of a string (the current directory name) as an arg. */ | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | rl_icppfunc_t *rl_directory_completion_hook = (rl_icppfunc_t *)NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | rl_icppfunc_t *rl_directory_rewrite_hook = (rl_icppfunc_t *)NULL; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | /* Non-zero means readline completion functions perform tilde expansion. */ | 
					
						
							|  |  |  | int rl_complete_with_tilde_expansion = 0; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | /* Pointer to the generator function for completion_matches ().
 | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |    NULL means to use rl_filename_completion_function (), the default filename | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |    completer. */ | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | rl_compentry_func_t *rl_completion_entry_function = (rl_compentry_func_t *)NULL; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | /* Pointer to generator function for rl_menu_complete ().  NULL means to use
 | 
					
						
							|  |  |  |    *rl_completion_entry_function (see above). */ | 
					
						
							|  |  |  | rl_compentry_func_t *rl_menu_completion_entry_function = (rl_compentry_func_t *)NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | /* Pointer to alternative function to create matches.
 | 
					
						
							|  |  |  |    Function is called with TEXT, START, and END. | 
					
						
							|  |  |  |    START and END are indices in RL_LINE_BUFFER saying what the boundaries | 
					
						
							|  |  |  |    of TEXT are. | 
					
						
							|  |  |  |    If this function exists and returns NULL then call the value of | 
					
						
							|  |  |  |    rl_completion_entry_function to try to match, otherwise use the | 
					
						
							|  |  |  |    array of strings returned. */ | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | rl_completion_func_t *rl_attempted_completion_function = (rl_completion_func_t *)NULL; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* Non-zero means to suppress normal filename completion after the
 | 
					
						
							|  |  |  |    user-specified completion function has been called. */ | 
					
						
							|  |  |  | int rl_attempted_completion_over = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | /* Set to a character indicating the type of completion being performed
 | 
					
						
							|  |  |  |    by rl_complete_internal, available for use by application completion | 
					
						
							|  |  |  |    functions. */ | 
					
						
							|  |  |  | int rl_completion_type = 0; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* Up to this many items will be displayed in response to a
 | 
					
						
							|  |  |  |    possible-completions call.  After that, we ask the user if | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |    she is sure she wants to see them all.  A negative value means | 
					
						
							|  |  |  |    don't ask. */ | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | int rl_completion_query_items = 100; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | int _rl_page_completions = 1; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | /* The basic list of characters that signal a break between words for the
 | 
					
						
							|  |  |  |    completer routine.  The contents of this variable is what breaks words | 
					
						
							|  |  |  |    in the shell, i.e. " \t\n\"\\'`@$><=" */ | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | const char *rl_basic_word_break_characters = " \t\n\"\\'`@$><=;|&{("; /* }) */ | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | /* List of basic quoting characters. */ | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | const char *rl_basic_quote_characters = "\"'"; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | /* The list of characters that signal a break between words for
 | 
					
						
							|  |  |  |    rl_complete_internal.  The default list is the contents of | 
					
						
							|  |  |  |    rl_basic_word_break_characters.  */ | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | /*const*/ char *rl_completer_word_break_characters = (/*const*/ char *)NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Hook function to allow an application to set the completion word
 | 
					
						
							|  |  |  |    break characters before readline breaks up the line.  Allows | 
					
						
							|  |  |  |    position-dependent word break characters. */ | 
					
						
							|  |  |  | rl_cpvfunc_t *rl_completion_word_break_hook = (rl_cpvfunc_t *)NULL; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* List of characters which can be used to quote a substring of the line.
 | 
					
						
							|  |  |  |    Completion occurs on the entire substring, and within the substring | 
					
						
							|  |  |  |    rl_completer_word_break_characters are treated as any other character, | 
					
						
							|  |  |  |    unless they also appear within this list. */ | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | const char *rl_completer_quote_characters = (const char *)NULL; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | /* List of characters that should be quoted in filenames by the completer. */ | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | const char *rl_filename_quote_characters = (const char *)NULL; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | /* List of characters that are word break characters, but should be left
 | 
					
						
							|  |  |  |    in TEXT when it is passed to the completion function.  The shell uses | 
					
						
							|  |  |  |    this to help determine what kind of completing to do. */ | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | const char *rl_special_prefixes = (const char *)NULL; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* If non-zero, then disallow duplicates in the matches. */ | 
					
						
							|  |  |  | int rl_ignore_completion_duplicates = 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Non-zero means that the results of the matches are to be treated
 | 
					
						
							|  |  |  |    as filenames.  This is ALWAYS zero on entry, and can only be changed | 
					
						
							|  |  |  |    within a completion entry finder function. */ | 
					
						
							|  |  |  | int rl_filename_completion_desired = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Non-zero means that the results of the matches are to be quoted using
 | 
					
						
							|  |  |  |    double quotes (or an application-specific quoting mechanism) if the | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |    filename contains any characters in rl_filename_quote_chars.  This is | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |    ALWAYS non-zero on entry, and can only be changed within a completion | 
					
						
							|  |  |  |    entry finder function. */ | 
					
						
							|  |  |  | int rl_filename_quoting_desired = 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* This function, if defined, is called by the completer when real
 | 
					
						
							|  |  |  |    filename completion is done, after all the matching names have been | 
					
						
							|  |  |  |    generated. It is passed a (char**) known as matches in the code below. | 
					
						
							|  |  |  |    It consists of a NULL-terminated array of pointers to potential | 
					
						
							|  |  |  |    matching strings.  The 1st element (matches[0]) is the maximal | 
					
						
							|  |  |  |    substring that is common to all matches. This function can re-arrange | 
					
						
							|  |  |  |    the list of matches as required, but all elements of the array must be | 
					
						
							|  |  |  |    free()'d if they are deleted. The main intent of this function is | 
					
						
							|  |  |  |    to implement FIGNORE a la SunOS csh. */ | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | rl_compignore_func_t *rl_ignore_some_completions_function = (rl_compignore_func_t *)NULL; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | /* Set to a function to quote a filename in an application-specific fashion.
 | 
					
						
							|  |  |  |    Called with the text to quote, the type of match found (single or multiple) | 
					
						
							|  |  |  |    and a pointer to the quoting character to be used, which the function can | 
					
						
							|  |  |  |    reset if desired. */ | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | rl_quote_func_t *rl_filename_quoting_function = rl_quote_filename; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |           | 
					
						
							|  |  |  | /* Function to call to remove quoting characters from a filename.  Called
 | 
					
						
							|  |  |  |    before completion is attempted, so the embedded quotes do not interfere | 
					
						
							|  |  |  |    with matching names in the file system.  Readline doesn't do anything | 
					
						
							|  |  |  |    with this; it's set only by applications. */ | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | rl_dequote_func_t *rl_filename_dequoting_function = (rl_dequote_func_t *)NULL; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* Function to call to decide whether or not a word break character is
 | 
					
						
							|  |  |  |    quoted.  If a character is quoted, it does not break words for the | 
					
						
							|  |  |  |    completer. */ | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | rl_linebuf_func_t *rl_char_is_quoted_p = (rl_linebuf_func_t *)NULL; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | /* If non-zero, the completion functions don't append anything except a
 | 
					
						
							|  |  |  |    possible closing quote.  This is set to 0 by rl_complete_internal and | 
					
						
							|  |  |  |    may be changed by an application-specific completion function. */ | 
					
						
							|  |  |  | int rl_completion_suppress_append = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | /* Character appended to completed words when at the end of the line.  The
 | 
					
						
							|  |  |  |    default is a space. */ | 
					
						
							|  |  |  | int rl_completion_append_character = ' '; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | /* If non-zero, the completion functions don't append any closing quote.
 | 
					
						
							|  |  |  |    This is set to 0 by rl_complete_internal and may be changed by an | 
					
						
							|  |  |  |    application-specific completion function. */ | 
					
						
							|  |  |  | int rl_completion_suppress_quote = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Set to any quote character readline thinks it finds before any application
 | 
					
						
							|  |  |  |    completion function is called. */ | 
					
						
							|  |  |  | int rl_completion_quote_character; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Set to a non-zero value if readline found quoting anywhere in the word to
 | 
					
						
							|  |  |  |    be completed; set before any application completion function is called. */ | 
					
						
							|  |  |  | int rl_completion_found_quote; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | /* If non-zero, a slash will be appended to completed filenames that are
 | 
					
						
							|  |  |  |    symbolic links to directory names, subject to the value of the | 
					
						
							|  |  |  |    mark-directories variable (which is user-settable).  This exists so | 
					
						
							|  |  |  |    that application completion functions can override the user's preference | 
					
						
							|  |  |  |    (set via the mark-symlinked-directories variable) if appropriate. | 
					
						
							|  |  |  |    It's set to the value of _rl_complete_mark_symlink_dirs in | 
					
						
							|  |  |  |    rl_complete_internal before any application-specific completion | 
					
						
							|  |  |  |    function is called, so without that function doing anything, the user's | 
					
						
							|  |  |  |    preferences are honored. */ | 
					
						
							|  |  |  | int rl_completion_mark_symlink_dirs; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | /* If non-zero, inhibit completion (temporarily). */ | 
					
						
							|  |  |  | int rl_inhibit_completion; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | /* Set to the last key used to invoke one of the completion functions */ | 
					
						
							|  |  |  | int rl_completion_invoking_key; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* If non-zero, sort the completion matches.  On by default. */ | 
					
						
							|  |  |  | int rl_sort_completion_matches = 1; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | /* Variables local to this file. */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Local variable states what happened during the last completion attempt. */ | 
					
						
							|  |  |  | static int completion_changed_buffer; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | /* The result of the query to the user about displaying completion matches */ | 
					
						
							|  |  |  | static int completion_y_or_n; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | /*************************************/ | 
					
						
							|  |  |  | /*				     */ | 
					
						
							|  |  |  | /*    Bindable completion functions  */ | 
					
						
							|  |  |  | /*				     */ | 
					
						
							|  |  |  | /*************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | /* Complete the word at or before point.  You have supplied the function
 | 
					
						
							|  |  |  |    that does the initial simple matching selection algorithm (see | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |    rl_completion_matches ()).  The default is to do filename completion. */ | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | int | 
					
						
							|  |  |  | rl_complete (ignore, invoking_key) | 
					
						
							|  |  |  |      int ignore, invoking_key; | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |   rl_completion_invoking_key = invoking_key; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   if (rl_inhibit_completion) | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |     return (_rl_insert_char (ignore, invoking_key)); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   else if (rl_last_func == rl_complete && !completion_changed_buffer) | 
					
						
							|  |  |  |     return (rl_complete_internal ('?')); | 
					
						
							|  |  |  |   else if (_rl_complete_show_all) | 
					
						
							|  |  |  |     return (rl_complete_internal ('!')); | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |   else if (_rl_complete_show_unmodified) | 
					
						
							|  |  |  |     return (rl_complete_internal ('@')); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   else | 
					
						
							|  |  |  |     return (rl_complete_internal (TAB)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* List the possible completions.  See description of rl_complete (). */ | 
					
						
							|  |  |  | int | 
					
						
							|  |  |  | rl_possible_completions (ignore, invoking_key) | 
					
						
							|  |  |  |      int ignore, invoking_key; | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |   rl_completion_invoking_key = invoking_key; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   return (rl_complete_internal ('?')); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int | 
					
						
							|  |  |  | rl_insert_completions (ignore, invoking_key) | 
					
						
							|  |  |  |      int ignore, invoking_key; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |   rl_completion_invoking_key = invoking_key; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   return (rl_complete_internal ('*')); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | /* Return the correct value to pass to rl_complete_internal performing
 | 
					
						
							|  |  |  |    the same tests as rl_complete.  This allows consecutive calls to an | 
					
						
							|  |  |  |    application's completion function to list possible completions and for | 
					
						
							|  |  |  |    an application-specific completion function to honor the | 
					
						
							|  |  |  |    show-all-if-ambiguous readline variable. */ | 
					
						
							|  |  |  | int | 
					
						
							|  |  |  | rl_completion_mode (cfunc) | 
					
						
							|  |  |  |      rl_command_func_t *cfunc; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if (rl_last_func == cfunc && !completion_changed_buffer) | 
					
						
							|  |  |  |     return '?'; | 
					
						
							|  |  |  |   else if (_rl_complete_show_all) | 
					
						
							|  |  |  |     return '!'; | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |   else if (_rl_complete_show_unmodified) | 
					
						
							|  |  |  |     return '@'; | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   else | 
					
						
							|  |  |  |     return TAB; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | /************************************/ | 
					
						
							|  |  |  | /*				    */ | 
					
						
							|  |  |  | /*    Completion utility functions  */ | 
					
						
							|  |  |  | /*				    */ | 
					
						
							|  |  |  | /************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | /* Reset readline state on a signal or other event. */ | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | _rl_reset_completion_state () | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   rl_completion_found_quote = 0; | 
					
						
							|  |  |  |   rl_completion_quote_character = 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | /* Set default values for readline word completion.  These are the variables
 | 
					
						
							|  |  |  |    that application completion functions can change or inspect. */ | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | set_completion_defaults (what_to_do) | 
					
						
							|  |  |  |      int what_to_do; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   /* Only the completion entry function can change these. */ | 
					
						
							|  |  |  |   rl_filename_completion_desired = 0; | 
					
						
							|  |  |  |   rl_filename_quoting_desired = 1; | 
					
						
							|  |  |  |   rl_completion_type = what_to_do; | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |   rl_completion_suppress_append = rl_completion_suppress_quote = 0; | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |   rl_completion_append_character = ' '; | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* The completion entry function may optionally change this. */ | 
					
						
							|  |  |  |   rl_completion_mark_symlink_dirs = _rl_complete_mark_symlink_dirs; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | /* The user must press "y" or "n". Non-zero return means "y" pressed. */ | 
					
						
							|  |  |  | static int | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | get_y_or_n (for_pager) | 
					
						
							|  |  |  |      int for_pager; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | { | 
					
						
							|  |  |  |   int c; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for (;;) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |       RL_SETSTATE(RL_STATE_MOREINPUT); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |       c = rl_read_key (); | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |       RL_UNSETSTATE(RL_STATE_MOREINPUT); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |       if (c == 'y' || c == 'Y' || c == ' ') | 
					
						
							|  |  |  | 	return (1); | 
					
						
							|  |  |  |       if (c == 'n' || c == 'N' || c == RUBOUT) | 
					
						
							|  |  |  | 	return (0); | 
					
						
							| 
									
										
										
										
											2008-11-18 13:15:12 +00:00
										 |  |  |       if (c == ABORT_CHAR || c < 0) | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	_rl_abort_internal (); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |       if (for_pager && (c == NEWLINE || c == RETURN)) | 
					
						
							|  |  |  | 	return (2); | 
					
						
							|  |  |  |       if (for_pager && (c == 'q' || c == 'Q')) | 
					
						
							|  |  |  | 	return (0); | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |       rl_ding (); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | static int | 
					
						
							|  |  |  | _rl_internal_pager (lines) | 
					
						
							|  |  |  |      int lines; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   int i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   fprintf (rl_outstream, "--More--"); | 
					
						
							|  |  |  |   fflush (rl_outstream); | 
					
						
							|  |  |  |   i = get_y_or_n (1); | 
					
						
							|  |  |  |   _rl_erase_entire_line (); | 
					
						
							|  |  |  |   if (i == 0) | 
					
						
							|  |  |  |     return -1; | 
					
						
							|  |  |  |   else if (i == 2) | 
					
						
							|  |  |  |     return (lines - 1); | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | static int | 
					
						
							|  |  |  | path_isdir (filename) | 
					
						
							|  |  |  |      const char *filename; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   struct stat finfo; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return (stat (filename, &finfo) == 0 && S_ISDIR (finfo.st_mode)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | #if defined (VISIBLE_STATS)
 | 
					
						
							|  |  |  | /* Return the character which best describes FILENAME.
 | 
					
						
							|  |  |  |      `@' for symbolic links | 
					
						
							|  |  |  |      `/' for directories | 
					
						
							|  |  |  |      `*' for executables | 
					
						
							|  |  |  |      `=' for sockets | 
					
						
							|  |  |  |      `|' for FIFOs | 
					
						
							|  |  |  |      `%' for character special devices | 
					
						
							|  |  |  |      `#' for block special devices */ | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | stat_char (filename) | 
					
						
							|  |  |  |      char *filename; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   struct stat finfo; | 
					
						
							|  |  |  |   int character, r; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |   /* Short-circuit a //server on cygwin, since that will always behave as
 | 
					
						
							|  |  |  |      a directory. */ | 
					
						
							|  |  |  | #if __CYGWIN__
 | 
					
						
							|  |  |  |   if (filename[0] == '/' && filename[1] == '/' && strchr (filename+2, '/') == 0) | 
					
						
							|  |  |  |     return '/'; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | #if defined (HAVE_LSTAT) && defined (S_ISLNK)
 | 
					
						
							|  |  |  |   r = lstat (filename, &finfo); | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  |   r = stat (filename, &finfo); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (r == -1) | 
					
						
							|  |  |  |     return (0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   character = 0; | 
					
						
							|  |  |  |   if (S_ISDIR (finfo.st_mode)) | 
					
						
							|  |  |  |     character = '/'; | 
					
						
							|  |  |  | #if defined (S_ISCHR)
 | 
					
						
							|  |  |  |   else if (S_ISCHR (finfo.st_mode)) | 
					
						
							|  |  |  |     character = '%'; | 
					
						
							|  |  |  | #endif /* S_ISCHR */
 | 
					
						
							|  |  |  | #if defined (S_ISBLK)
 | 
					
						
							|  |  |  |   else if (S_ISBLK (finfo.st_mode)) | 
					
						
							|  |  |  |     character = '#'; | 
					
						
							|  |  |  | #endif /* S_ISBLK */
 | 
					
						
							|  |  |  | #if defined (S_ISLNK)
 | 
					
						
							|  |  |  |   else if (S_ISLNK (finfo.st_mode)) | 
					
						
							|  |  |  |     character = '@'; | 
					
						
							|  |  |  | #endif /* S_ISLNK */
 | 
					
						
							|  |  |  | #if defined (S_ISSOCK)
 | 
					
						
							|  |  |  |   else if (S_ISSOCK (finfo.st_mode)) | 
					
						
							|  |  |  |     character = '='; | 
					
						
							|  |  |  | #endif /* S_ISSOCK */
 | 
					
						
							|  |  |  | #if defined (S_ISFIFO)
 | 
					
						
							|  |  |  |   else if (S_ISFIFO (finfo.st_mode)) | 
					
						
							|  |  |  |     character = '|'; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |   else if (S_ISREG (finfo.st_mode)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       if (access (filename, X_OK) == 0) | 
					
						
							|  |  |  | 	character = '*'; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   return (character); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #endif /* VISIBLE_STATS */
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | /* Return the portion of PATHNAME that should be output when listing
 | 
					
						
							|  |  |  |    possible completions.  If we are hacking filename completion, we | 
					
						
							|  |  |  |    are only interested in the basename, the portion following the | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |    final slash.  Otherwise, we return what we were passed.  Since | 
					
						
							|  |  |  |    printing empty strings is not very informative, if we're doing | 
					
						
							|  |  |  |    filename completion, and the basename is the empty string, we look | 
					
						
							|  |  |  |    for the previous slash and return the portion following that.  If | 
					
						
							|  |  |  |    there's no previous slash, we just return what we were passed. */ | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | static char * | 
					
						
							|  |  |  | printable_part (pathname) | 
					
						
							|  |  |  |       char *pathname; | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   char *temp, *x; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (rl_filename_completion_desired == 0)	/* don't need to do anything */ | 
					
						
							|  |  |  |     return (pathname); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   temp = strrchr (pathname, '/'); | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | #if defined (__MSDOS__)
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   if (temp == 0 && ISALPHA ((unsigned char)pathname[0]) && pathname[1] == ':') | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |     temp = pathname + 1; | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if (temp == 0 || *temp == '\0') | 
					
						
							|  |  |  |     return (pathname); | 
					
						
							|  |  |  |   /* If the basename is NULL, we might have a pathname like '/usr/src/'.
 | 
					
						
							|  |  |  |      Look for a previous slash and, if one is found, return the portion | 
					
						
							|  |  |  |      following that slash.  If there's no previous slash, just return the | 
					
						
							|  |  |  |      pathname we were passed. */ | 
					
						
							|  |  |  |   else if (temp[1] == '\0') | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       for (x = temp - 1; x > pathname; x--) | 
					
						
							|  |  |  |         if (*x == '/') | 
					
						
							|  |  |  |           break; | 
					
						
							|  |  |  |       return ((*x == '/') ? x + 1 : pathname); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     return ++temp; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | /* Compute width of STRING when displayed on screen by print_filename */ | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | fnwidth (string) | 
					
						
							|  |  |  |      const char *string; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   int width, pos; | 
					
						
							|  |  |  | #if defined (HANDLE_MULTIBYTE)
 | 
					
						
							|  |  |  |   mbstate_t ps; | 
					
						
							|  |  |  |   int left, w; | 
					
						
							|  |  |  |   size_t clen; | 
					
						
							|  |  |  |   wchar_t wc; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   left = strlen (string) + 1; | 
					
						
							|  |  |  |   memset (&ps, 0, sizeof (mbstate_t)); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   width = pos = 0; | 
					
						
							|  |  |  |   while (string[pos]) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |       if (CTRL_CHAR (string[pos]) || string[pos] == RUBOUT) | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 	  width += 2; | 
					
						
							|  |  |  | 	  pos++; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | #if defined (HANDLE_MULTIBYTE)
 | 
					
						
							|  |  |  | 	  clen = mbrtowc (&wc, string + pos, left - pos, &ps); | 
					
						
							|  |  |  | 	  if (MB_INVALIDCH (clen)) | 
					
						
							|  |  |  | 	    { | 
					
						
							|  |  |  | 	      width++; | 
					
						
							|  |  |  | 	      pos++; | 
					
						
							|  |  |  | 	      memset (&ps, 0, sizeof (mbstate_t)); | 
					
						
							|  |  |  | 	    } | 
					
						
							|  |  |  | 	  else if (MB_NULLWCH (clen)) | 
					
						
							|  |  |  | 	    break; | 
					
						
							|  |  |  | 	  else | 
					
						
							|  |  |  | 	    { | 
					
						
							|  |  |  | 	      pos += clen; | 
					
						
							|  |  |  | 	      w = wcwidth (wc); | 
					
						
							|  |  |  | 	      width += (w >= 0) ? w : 1; | 
					
						
							|  |  |  | 	    } | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | 	  width++; | 
					
						
							|  |  |  | 	  pos++; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return width; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | #define ELLIPSIS_LEN	3
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | static int | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | fnprint (to_print, prefix_bytes) | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |      const char *to_print; | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |      int prefix_bytes; | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |   int printed_len, w; | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |   const char *s; | 
					
						
							|  |  |  | #if defined (HANDLE_MULTIBYTE)
 | 
					
						
							|  |  |  |   mbstate_t ps; | 
					
						
							|  |  |  |   const char *end; | 
					
						
							|  |  |  |   size_t tlen; | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |   int width; | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |   wchar_t wc; | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   end = to_print + strlen (to_print) + 1; | 
					
						
							|  |  |  |   memset (&ps, 0, sizeof (mbstate_t)); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   printed_len = 0; | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* Don't print only the ellipsis if the common prefix is one of the
 | 
					
						
							|  |  |  |      possible completions */ | 
					
						
							|  |  |  |   if (to_print[prefix_bytes] == '\0') | 
					
						
							|  |  |  |     prefix_bytes = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (prefix_bytes) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       char ellipsis; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       ellipsis = (to_print[prefix_bytes] == '.') ? '_' : '.'; | 
					
						
							|  |  |  |       for (w = 0; w < ELLIPSIS_LEN; w++) | 
					
						
							|  |  |  | 	putc (ellipsis, rl_outstream); | 
					
						
							|  |  |  |       printed_len = ELLIPSIS_LEN; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   s = to_print + prefix_bytes; | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |   while (*s) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       if (CTRL_CHAR (*s)) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |           putc ('^', rl_outstream); | 
					
						
							|  |  |  |           putc (UNCTRL (*s), rl_outstream); | 
					
						
							|  |  |  |           printed_len += 2; | 
					
						
							|  |  |  |           s++; | 
					
						
							|  |  |  | #if defined (HANDLE_MULTIBYTE)
 | 
					
						
							|  |  |  | 	  memset (&ps, 0, sizeof (mbstate_t)); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       else if (*s == RUBOUT) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  putc ('^', rl_outstream); | 
					
						
							|  |  |  | 	  putc ('?', rl_outstream); | 
					
						
							|  |  |  | 	  printed_len += 2; | 
					
						
							|  |  |  | 	  s++; | 
					
						
							|  |  |  | #if defined (HANDLE_MULTIBYTE)
 | 
					
						
							|  |  |  | 	  memset (&ps, 0, sizeof (mbstate_t)); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | #if defined (HANDLE_MULTIBYTE)
 | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  | 	  tlen = mbrtowc (&wc, s, end - s, &ps); | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | 	  if (MB_INVALIDCH (tlen)) | 
					
						
							|  |  |  | 	    { | 
					
						
							|  |  |  | 	      tlen = 1; | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  | 	      width = 1; | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | 	      memset (&ps, 0, sizeof (mbstate_t)); | 
					
						
							|  |  |  | 	    } | 
					
						
							|  |  |  | 	  else if (MB_NULLWCH (tlen)) | 
					
						
							|  |  |  | 	    break; | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  | 	  else | 
					
						
							|  |  |  | 	    { | 
					
						
							|  |  |  | 	      w = wcwidth (wc); | 
					
						
							|  |  |  | 	      width = (w >= 0) ? w : 1; | 
					
						
							|  |  |  | 	    } | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | 	  fwrite (s, 1, tlen, rl_outstream); | 
					
						
							|  |  |  | 	  s += tlen; | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  | 	  printed_len += width; | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | #else
 | 
					
						
							|  |  |  | 	  putc (*s, rl_outstream); | 
					
						
							|  |  |  | 	  s++; | 
					
						
							|  |  |  | 	  printed_len++; | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return printed_len; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | /* Output TO_PRINT to rl_outstream.  If VISIBLE_STATS is defined and we
 | 
					
						
							|  |  |  |    are using it, check for and output a single character for `special' | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |    filenames.  Return the number of characters we output. */ | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | static int | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | print_filename (to_print, full_pathname, prefix_bytes) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |      char *to_print, *full_pathname; | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |      int prefix_bytes; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |   int printed_len, extension_char, slen, tlen; | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |   char *s, c, *new_full_pathname, *dn; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |   extension_char = 0; | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |   printed_len = fnprint (to_print, prefix_bytes); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | #if defined (VISIBLE_STATS)
 | 
					
						
							|  |  |  |  if (rl_filename_completion_desired && (rl_visible_stats || _rl_complete_mark_directories)) | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  |  if (rl_filename_completion_desired && _rl_complete_mark_directories) | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     { | 
					
						
							|  |  |  |       /* If to_print != full_pathname, to_print is the basename of the
 | 
					
						
							|  |  |  | 	 path passed.  In this case, we try to expand the directory | 
					
						
							|  |  |  | 	 name before checking for the stat character. */ | 
					
						
							|  |  |  |       if (to_print != full_pathname) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  /* Terminate the directory name. */ | 
					
						
							|  |  |  | 	  c = to_print[-1]; | 
					
						
							|  |  |  | 	  to_print[-1] = '\0'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | 	  /* If setting the last slash in full_pathname to a NUL results in
 | 
					
						
							|  |  |  | 	     full_pathname being the empty string, we are trying to complete | 
					
						
							|  |  |  | 	     files in the root directory.  If we pass a null string to the | 
					
						
							|  |  |  | 	     bash directory completion hook, for example, it will expand it | 
					
						
							|  |  |  | 	     to the current directory.  We just want the `/'. */ | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  | 	  if (full_pathname == 0 || *full_pathname == 0) | 
					
						
							|  |  |  | 	    dn = "/"; | 
					
						
							|  |  |  | 	  else if (full_pathname[0] != '/') | 
					
						
							|  |  |  | 	    dn = full_pathname; | 
					
						
							|  |  |  | 	  else if (full_pathname[1] == 0) | 
					
						
							|  |  |  | 	    dn = "//";		/* restore trailing slash to `//' */ | 
					
						
							|  |  |  | 	  else if (full_pathname[1] == '/' && full_pathname[2] == 0) | 
					
						
							|  |  |  | 	    dn = "/";		/* don't turn /// into // */ | 
					
						
							|  |  |  | 	  else | 
					
						
							|  |  |  | 	    dn = full_pathname; | 
					
						
							|  |  |  | 	  s = tilde_expand (dn); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	  if (rl_directory_completion_hook) | 
					
						
							|  |  |  | 	    (*rl_directory_completion_hook) (&s); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	  slen = strlen (s); | 
					
						
							|  |  |  | 	  tlen = strlen (to_print); | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | 	  new_full_pathname = (char *)xmalloc (slen + tlen + 2); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	  strcpy (new_full_pathname, s); | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  | 	  if (s[slen - 1] == '/') | 
					
						
							|  |  |  | 	    slen--; | 
					
						
							|  |  |  | 	  else | 
					
						
							|  |  |  | 	    new_full_pathname[slen] = '/'; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	  new_full_pathname[slen] = '/'; | 
					
						
							|  |  |  | 	  strcpy (new_full_pathname + slen + 1, to_print); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | #if defined (VISIBLE_STATS)
 | 
					
						
							|  |  |  | 	  if (rl_visible_stats) | 
					
						
							|  |  |  | 	    extension_char = stat_char (new_full_pathname); | 
					
						
							|  |  |  | 	  else | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 	  if (path_isdir (new_full_pathname)) | 
					
						
							|  |  |  | 	    extension_char = '/'; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	  free (new_full_pathname); | 
					
						
							|  |  |  | 	  to_print[-1] = c; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  s = tilde_expand (full_pathname); | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | #if defined (VISIBLE_STATS)
 | 
					
						
							|  |  |  | 	  if (rl_visible_stats) | 
					
						
							|  |  |  | 	    extension_char = stat_char (s); | 
					
						
							|  |  |  | 	  else | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 	    if (path_isdir (s)) | 
					
						
							|  |  |  | 	      extension_char = '/'; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       free (s); | 
					
						
							|  |  |  |       if (extension_char) | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 	  putc (extension_char, rl_outstream); | 
					
						
							|  |  |  | 	  printed_len++; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |   return printed_len; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | static char * | 
					
						
							|  |  |  | rl_quote_filename (s, rtype, qcp) | 
					
						
							|  |  |  |      char *s; | 
					
						
							|  |  |  |      int rtype; | 
					
						
							|  |  |  |      char *qcp; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   char *r; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |   r = (char *)xmalloc (strlen (s) + 2); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   *r = *rl_completer_quote_characters; | 
					
						
							|  |  |  |   strcpy (r + 1, s); | 
					
						
							|  |  |  |   if (qcp) | 
					
						
							|  |  |  |     *qcp = *rl_completer_quote_characters; | 
					
						
							|  |  |  |   return r; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | /* Find the bounds of the current word for completion purposes, and leave
 | 
					
						
							|  |  |  |    rl_point set to the end of the word.  This function skips quoted | 
					
						
							|  |  |  |    substrings (characters between matched pairs of characters in | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |    rl_completer_quote_characters).  First we try to find an unclosed | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |    quoted substring on which to do matching.  If one is not found, we use | 
					
						
							|  |  |  |    the word break characters to find the boundaries of the current word. | 
					
						
							|  |  |  |    We call an application-specific function to decide whether or not a | 
					
						
							|  |  |  |    particular word break character is quoted; if that function returns a | 
					
						
							|  |  |  |    non-zero result, the character does not break a word.  This function | 
					
						
							|  |  |  |    returns the opening quote character if we found an unclosed quoted | 
					
						
							|  |  |  |    substring, '\0' otherwise.  FP, if non-null, is set to a value saying | 
					
						
							|  |  |  |    which (shell-like) quote characters we found (single quote, double | 
					
						
							|  |  |  |    quote, or backslash) anywhere in the string.  DP, if non-null, is set to | 
					
						
							|  |  |  |    the value of the delimiter character that caused a word break. */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | char | 
					
						
							|  |  |  | _rl_find_completion_word (fp, dp) | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |      int *fp, *dp; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   int scan, end, found_quote, delimiter, pass_next, isbrk; | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |   char quote_char, *brkchars; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   end = rl_point; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   found_quote = delimiter = 0; | 
					
						
							|  |  |  |   quote_char = '\0'; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |   brkchars = 0; | 
					
						
							|  |  |  |   if (rl_completion_word_break_hook) | 
					
						
							|  |  |  |     brkchars = (*rl_completion_word_break_hook) (); | 
					
						
							|  |  |  |   if (brkchars == 0) | 
					
						
							|  |  |  |     brkchars = rl_completer_word_break_characters; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   if (rl_completer_quote_characters) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |       /* We have a list of characters which can be used in pairs to
 | 
					
						
							|  |  |  | 	 quote substrings for the completer.  Try to find the start | 
					
						
							|  |  |  | 	 of an unclosed quoted substring. */ | 
					
						
							|  |  |  |       /* FOUND_QUOTE is set so we know what kind of quotes we found. */ | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |       for (scan = pass_next = 0; scan < end; scan = MB_NEXTCHAR (rl_line_buffer, scan, 1, MB_FIND_ANY)) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	  if (pass_next) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	    { | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	      pass_next = 0; | 
					
						
							|  |  |  | 	      continue; | 
					
						
							|  |  |  | 	    } | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | 	  /* Shell-like semantics for single quotes -- don't allow backslash
 | 
					
						
							|  |  |  | 	     to quote anything in single quotes, especially not the closing | 
					
						
							|  |  |  | 	     quote.  If you don't like this, take out the check on the value | 
					
						
							|  |  |  | 	     of quote_char. */ | 
					
						
							|  |  |  | 	  if (quote_char != '\'' && rl_line_buffer[scan] == '\\') | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	    { | 
					
						
							|  |  |  | 	      pass_next = 1; | 
					
						
							|  |  |  | 	      found_quote |= RL_QF_BACKSLASH; | 
					
						
							|  |  |  | 	      continue; | 
					
						
							|  |  |  | 	    } | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	  if (quote_char != '\0') | 
					
						
							|  |  |  | 	    { | 
					
						
							|  |  |  | 	      /* Ignore everything until the matching close quote char. */ | 
					
						
							|  |  |  | 	      if (rl_line_buffer[scan] == quote_char) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 		{ | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 		  /* Found matching close.  Abandon this substring. */ | 
					
						
							|  |  |  | 		  quote_char = '\0'; | 
					
						
							|  |  |  | 		  rl_point = end; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	    } | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	  else if (strchr (rl_completer_quote_characters, rl_line_buffer[scan])) | 
					
						
							|  |  |  | 	    { | 
					
						
							|  |  |  | 	      /* Found start of a quoted substring. */ | 
					
						
							|  |  |  | 	      quote_char = rl_line_buffer[scan]; | 
					
						
							|  |  |  | 	      rl_point = scan + 1; | 
					
						
							|  |  |  | 	      /* Shell-like quoting conventions. */ | 
					
						
							|  |  |  | 	      if (quote_char == '\'') | 
					
						
							|  |  |  | 		found_quote |= RL_QF_SINGLE_QUOTE; | 
					
						
							|  |  |  | 	      else if (quote_char == '"') | 
					
						
							|  |  |  | 		found_quote |= RL_QF_DOUBLE_QUOTE; | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 	      else | 
					
						
							|  |  |  | 		found_quote |= RL_QF_OTHER_QUOTE;       | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	    } | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   if (rl_point == end && quote_char == '\0') | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       /* We didn't find an unclosed quoted substring upon which to do
 | 
					
						
							|  |  |  |          completion, so use the word break characters to find the | 
					
						
							|  |  |  |          substring on which to complete. */ | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |       while (rl_point = MB_PREVCHAR (rl_line_buffer, rl_point, MB_FIND_ANY)) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	  scan = rl_line_buffer[rl_point]; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | 	  if (strchr (brkchars, scan) == 0) | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	    continue; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	  /* Call the application-specific function to tell us whether
 | 
					
						
							|  |  |  | 	     this word break character is quoted and should be skipped. */ | 
					
						
							|  |  |  | 	  if (rl_char_is_quoted_p && found_quote && | 
					
						
							|  |  |  | 	      (*rl_char_is_quoted_p) (rl_line_buffer, rl_point)) | 
					
						
							|  |  |  | 	    continue; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	  /* Convoluted code, but it avoids an n^2 algorithm with calls
 | 
					
						
							|  |  |  | 	     to char_is_quoted. */ | 
					
						
							|  |  |  | 	  break; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   /* If we are at an unquoted word break, then advance past it. */ | 
					
						
							|  |  |  |   scan = rl_line_buffer[rl_point]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* If there is an application-specific function to say whether or not
 | 
					
						
							|  |  |  |      a character is quoted and we found a quote character, let that | 
					
						
							|  |  |  |      function decide whether or not a character is a word break, even | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |      if it is found in rl_completer_word_break_characters.  Don't bother | 
					
						
							|  |  |  |      if we're at the end of the line, though. */ | 
					
						
							|  |  |  |   if (scan) | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |       if (rl_char_is_quoted_p) | 
					
						
							|  |  |  | 	isbrk = (found_quote == 0 || | 
					
						
							|  |  |  | 		(*rl_char_is_quoted_p) (rl_line_buffer, rl_point) == 0) && | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | 		strchr (brkchars, scan) != 0; | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |       else | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | 	isbrk = strchr (brkchars, scan) != 0; | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |       if (isbrk) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  /* If the character that caused the word break was a quoting
 | 
					
						
							|  |  |  | 	     character, then remember it as the delimiter. */ | 
					
						
							|  |  |  | 	  if (rl_basic_quote_characters && | 
					
						
							|  |  |  | 	      strchr (rl_basic_quote_characters, scan) && | 
					
						
							|  |  |  | 	      (end - rl_point) > 1) | 
					
						
							|  |  |  | 	    delimiter = scan; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	  /* If the character isn't needed to determine something special
 | 
					
						
							|  |  |  | 	     about what kind of completion to perform, then advance past it. */ | 
					
						
							|  |  |  | 	  if (rl_special_prefixes == 0 || strchr (rl_special_prefixes, scan) == 0) | 
					
						
							|  |  |  | 	    rl_point++; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (fp) | 
					
						
							|  |  |  |     *fp = found_quote; | 
					
						
							|  |  |  |   if (dp) | 
					
						
							|  |  |  |     *dp = delimiter; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return (quote_char); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static char ** | 
					
						
							|  |  |  | gen_completion_matches (text, start, end, our_func, found_quote, quote_char) | 
					
						
							|  |  |  |      char *text; | 
					
						
							|  |  |  |      int start, end; | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |      rl_compentry_func_t *our_func; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |      int found_quote, quote_char; | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2006-10-10 14:15:34 +00:00
										 |  |  |   char **matches; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |   rl_completion_found_quote = found_quote; | 
					
						
							|  |  |  |   rl_completion_quote_character = quote_char; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |   /* If the user wants to TRY to complete, but then wants to give
 | 
					
						
							|  |  |  |      up and use the default completion function, they set the | 
					
						
							|  |  |  |      variable rl_attempted_completion_function. */ | 
					
						
							|  |  |  |   if (rl_attempted_completion_function) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       matches = (*rl_attempted_completion_function) (text, start, end); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (matches || rl_attempted_completion_over) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  rl_attempted_completion_over = 0; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	  return (matches); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-10-10 14:15:34 +00:00
										 |  |  |   /* XXX -- filename dequoting moved into rl_filename_completion_function */ | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |   matches = rl_completion_matches (text, our_func); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   return matches;   | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | /* Filter out duplicates in MATCHES.  This frees up the strings in
 | 
					
						
							|  |  |  |    MATCHES. */ | 
					
						
							|  |  |  | static char ** | 
					
						
							|  |  |  | remove_duplicate_matches (matches) | 
					
						
							|  |  |  |      char **matches; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   char *lowest_common; | 
					
						
							|  |  |  |   int i, j, newlen; | 
					
						
							|  |  |  |   char dead_slot; | 
					
						
							|  |  |  |   char **temp_array; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   /* Sort the items. */ | 
					
						
							|  |  |  |   for (i = 0; matches[i]; i++) | 
					
						
							|  |  |  |     ; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* Sort the array without matches[0], since we need it to
 | 
					
						
							|  |  |  |      stay in place no matter what. */ | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |   if (i && rl_sort_completion_matches) | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |     qsort (matches+1, i-1, sizeof (char *), (QSFUNC *)_rl_qsort_string_compare); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* Remember the lowest common denominator for it may be unique. */ | 
					
						
							|  |  |  |   lowest_common = savestring (matches[0]); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   for (i = newlen = 0; matches[i + 1]; i++) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       if (strcmp (matches[i], matches[i + 1]) == 0) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	  free (matches[i]); | 
					
						
							|  |  |  | 	  matches[i] = (char *)&dead_slot; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  | 	newlen++; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   /* We have marked all the dead slots with (char *)&dead_slot.
 | 
					
						
							|  |  |  |      Copy all the non-dead entries into a new array. */ | 
					
						
							|  |  |  |   temp_array = (char **)xmalloc ((3 + newlen) * sizeof (char *)); | 
					
						
							|  |  |  |   for (i = j = 1; matches[i]; i++) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       if (matches[i] != (char *)&dead_slot) | 
					
						
							|  |  |  | 	temp_array[j++] = matches[i]; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   temp_array[j] = (char *)NULL; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   if (matches[0] != (char *)&dead_slot) | 
					
						
							|  |  |  |     free (matches[0]); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   /* Place the lowest common denominator back in [0]. */ | 
					
						
							|  |  |  |   temp_array[0] = lowest_common; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* If there is one string left, and it is identical to the
 | 
					
						
							|  |  |  |      lowest common denominator, then the LCD is the string to | 
					
						
							|  |  |  |      insert. */ | 
					
						
							|  |  |  |   if (j == 2 && strcmp (temp_array[0], temp_array[1]) == 0) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       free (temp_array[1]); | 
					
						
							|  |  |  |       temp_array[1] = (char *)NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   return (temp_array); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | /* Find the common prefix of the list of matches, and put it into
 | 
					
						
							|  |  |  |    matches[0]. */ | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | compute_lcd_of_matches (match_list, matches, text) | 
					
						
							|  |  |  |      char **match_list; | 
					
						
							|  |  |  |      int matches; | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |      const char *text; | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | { | 
					
						
							|  |  |  |   register int i, c1, c2, si; | 
					
						
							|  |  |  |   int low;		/* Count of max-matched characters. */ | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |   char *dtext;		/* dequoted TEXT, if needed */ | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | #if defined (HANDLE_MULTIBYTE)
 | 
					
						
							|  |  |  |   int v; | 
					
						
							|  |  |  |   mbstate_t ps1, ps2; | 
					
						
							|  |  |  |   wchar_t wc1, wc2; | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* If only one match, just use that.  Otherwise, compare each
 | 
					
						
							|  |  |  |      member of the list with the next, finding out where they | 
					
						
							|  |  |  |      stop matching. */ | 
					
						
							|  |  |  |   if (matches == 1) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       match_list[0] = match_list[1]; | 
					
						
							|  |  |  |       match_list[1] = (char *)NULL; | 
					
						
							|  |  |  |       return 1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for (i = 1, low = 100000; i < matches; i++) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | #if defined (HANDLE_MULTIBYTE)
 | 
					
						
							|  |  |  |       if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  memset (&ps1, 0, sizeof (mbstate_t)); | 
					
						
							|  |  |  | 	  memset (&ps2, 0, sizeof (mbstate_t)); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |       if (_rl_completion_case_fold) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  for (si = 0; | 
					
						
							|  |  |  | 	       (c1 = _rl_to_lower(match_list[i][si])) && | 
					
						
							|  |  |  | 	       (c2 = _rl_to_lower(match_list[i + 1][si])); | 
					
						
							|  |  |  | 	       si++) | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | #if defined (HANDLE_MULTIBYTE)
 | 
					
						
							|  |  |  | 	    if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) | 
					
						
							|  |  |  | 	      { | 
					
						
							|  |  |  | 		v = mbrtowc (&wc1, match_list[i]+si, strlen (match_list[i]+si), &ps1); | 
					
						
							|  |  |  | 		mbrtowc (&wc2, match_list[i+1]+si, strlen (match_list[i+1]+si), &ps2); | 
					
						
							|  |  |  | 		wc1 = towlower (wc1); | 
					
						
							|  |  |  | 		wc2 = towlower (wc2); | 
					
						
							|  |  |  | 		if (wc1 != wc2) | 
					
						
							|  |  |  | 		  break; | 
					
						
							|  |  |  | 		else if (v > 1) | 
					
						
							|  |  |  | 		  si += v - 1; | 
					
						
							|  |  |  | 	      } | 
					
						
							|  |  |  | 	    else | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | 	    if (c1 != c2) | 
					
						
							|  |  |  | 	      break; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  for (si = 0; | 
					
						
							|  |  |  | 	       (c1 = match_list[i][si]) && | 
					
						
							|  |  |  | 	       (c2 = match_list[i + 1][si]); | 
					
						
							|  |  |  | 	       si++) | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | #if defined (HANDLE_MULTIBYTE)
 | 
					
						
							|  |  |  | 	    if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) | 
					
						
							|  |  |  | 	      { | 
					
						
							| 
									
										
										
										
											2006-10-10 14:15:34 +00:00
										 |  |  | 		mbstate_t ps_back; | 
					
						
							|  |  |  | 		ps_back = ps1; | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 		if (!_rl_compare_chars (match_list[i], si, &ps1, match_list[i+1], si, &ps2)) | 
					
						
							|  |  |  | 		  break; | 
					
						
							|  |  |  | 		else if ((v = _rl_get_char_len (&match_list[i][si], &ps_back)) > 1) | 
					
						
							|  |  |  | 		  si += v - 1; | 
					
						
							|  |  |  | 	      } | 
					
						
							|  |  |  | 	    else | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | 	    if (c1 != c2) | 
					
						
							|  |  |  | 	      break; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (low > si) | 
					
						
							|  |  |  | 	low = si; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* If there were multiple matches, but none matched up to even the
 | 
					
						
							|  |  |  |      first character, and the user typed something, use that as the | 
					
						
							|  |  |  |      value of matches[0]. */ | 
					
						
							|  |  |  |   if (low == 0 && text && *text) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |       match_list[0] = (char *)xmalloc (strlen (text) + 1); | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |       strcpy (match_list[0], text); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |       match_list[0] = (char *)xmalloc (low + 1); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |       /* XXX - this might need changes in the presence of multibyte chars */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |       /* If we are ignoring case, try to preserve the case of the string
 | 
					
						
							|  |  |  | 	 the user typed in the face of multiple matches differing in case. */ | 
					
						
							|  |  |  |       if (_rl_completion_case_fold) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | 	  /* We're making an assumption here:
 | 
					
						
							|  |  |  | 		IF we're completing filenames AND | 
					
						
							|  |  |  | 		   the application has defined a filename dequoting function AND | 
					
						
							|  |  |  | 		   we found a quote character AND | 
					
						
							|  |  |  | 		   the application has requested filename quoting | 
					
						
							|  |  |  | 		THEN | 
					
						
							|  |  |  | 		   we assume that TEXT was dequoted before checking against | 
					
						
							|  |  |  | 		   the file system and needs to be dequoted here before we | 
					
						
							|  |  |  | 		   check against the list of matches | 
					
						
							|  |  |  | 		FI */ | 
					
						
							|  |  |  | 	  dtext = (char *)NULL; | 
					
						
							|  |  |  | 	  if (rl_filename_completion_desired && | 
					
						
							|  |  |  | 	      rl_filename_dequoting_function && | 
					
						
							|  |  |  | 	      rl_completion_found_quote && | 
					
						
							|  |  |  | 	      rl_filename_quoting_desired) | 
					
						
							|  |  |  | 	    { | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  | 	      dtext = (*rl_filename_dequoting_function) ((char *)text, rl_completion_quote_character); | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | 	      text = dtext; | 
					
						
							|  |  |  | 	    } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | 	  /* sort the list to get consistent answers. */ | 
					
						
							|  |  |  | 	  qsort (match_list+1, matches, sizeof(char *), (QSFUNC *)_rl_qsort_string_compare); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	  si = strlen (text); | 
					
						
							|  |  |  | 	  if (si <= low) | 
					
						
							|  |  |  | 	    { | 
					
						
							|  |  |  | 	      for (i = 1; i <= matches; i++) | 
					
						
							|  |  |  | 		if (strncmp (match_list[i], text, si) == 0) | 
					
						
							|  |  |  | 		  { | 
					
						
							|  |  |  | 		    strncpy (match_list[0], match_list[i], low); | 
					
						
							|  |  |  | 		    break; | 
					
						
							|  |  |  | 		  } | 
					
						
							|  |  |  | 	      /* no casematch, use first entry */ | 
					
						
							|  |  |  | 	      if (i > matches) | 
					
						
							|  |  |  | 		strncpy (match_list[0], match_list[1], low); | 
					
						
							|  |  |  | 	    } | 
					
						
							|  |  |  | 	  else | 
					
						
							|  |  |  | 	    /* otherwise, just use the text the user typed. */ | 
					
						
							|  |  |  | 	    strncpy (match_list[0], text, low); | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	  FREE (dtext); | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  |         strncpy (match_list[0], match_list[1], low); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |       match_list[0][low] = '\0'; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return matches; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							| 
									
										
										
										
											1999-02-19 17:11:39 +00:00
										 |  |  | postprocess_matches (matchesp, matching_filenames) | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |      char ***matchesp; | 
					
						
							|  |  |  |      int matching_filenames; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   char *t, **matches, **temp_matches; | 
					
						
							|  |  |  |   int nmatch, i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   matches = *matchesp; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   if (matches == 0) | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |   /* It seems to me that in all the cases we handle we would like
 | 
					
						
							|  |  |  |      to ignore duplicate possiblilities.  Scan for the text to | 
					
						
							|  |  |  |      insert being identical to the other completions. */ | 
					
						
							|  |  |  |   if (rl_ignore_completion_duplicates) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       temp_matches = remove_duplicate_matches (matches); | 
					
						
							|  |  |  |       free (matches); | 
					
						
							|  |  |  |       matches = temp_matches; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* If we are matching filenames, then here is our chance to
 | 
					
						
							|  |  |  |      do clever processing by re-examining the list.  Call the | 
					
						
							|  |  |  |      ignore function with the array as a parameter.  It can | 
					
						
							|  |  |  |      munge the array, deleting matches as it desires. */ | 
					
						
							|  |  |  |   if (rl_ignore_some_completions_function && matching_filenames) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       for (nmatch = 1; matches[nmatch]; nmatch++) | 
					
						
							|  |  |  | 	; | 
					
						
							|  |  |  |       (void)(*rl_ignore_some_completions_function) (matches); | 
					
						
							|  |  |  |       if (matches == 0 || matches[0] == 0) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  FREE (matches); | 
					
						
							|  |  |  | 	  *matchesp = (char **)0; | 
					
						
							|  |  |  | 	  return 0; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  /* If we removed some matches, recompute the common prefix. */ | 
					
						
							|  |  |  | 	  for (i = 1; matches[i]; i++) | 
					
						
							|  |  |  | 	    ; | 
					
						
							|  |  |  | 	  if (i > 1 && i < nmatch) | 
					
						
							|  |  |  | 	    { | 
					
						
							|  |  |  | 	      t = matches[0]; | 
					
						
							| 
									
										
										
										
											1999-02-19 17:11:39 +00:00
										 |  |  | 	      compute_lcd_of_matches (matches, i - 1, t); | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | 	      FREE (t); | 
					
						
							|  |  |  | 	    } | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   *matchesp = matches; | 
					
						
							|  |  |  |   return (1); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-02-19 17:11:39 +00:00
										 |  |  | /* A convenience function for displaying a list of strings in
 | 
					
						
							|  |  |  |    columnar format on readline's output stream.  MATCHES is the list | 
					
						
							|  |  |  |    of strings, in argv format, LEN is the number of strings in MATCHES, | 
					
						
							|  |  |  |    and MAX is the length of the longest string in MATCHES. */ | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | rl_display_match_list (matches, len, max) | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |      char **matches; | 
					
						
							| 
									
										
										
										
											1999-02-19 17:11:39 +00:00
										 |  |  |      int len, max; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   int count, limit, printed_len, lines; | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |   int i, j, k, l, common_length, sind; | 
					
						
							|  |  |  |   char *temp, *t; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* Find the length of the prefix common to all items: length as displayed
 | 
					
						
							|  |  |  |      characters (common_length) and as a byte index into the matches (sind) */ | 
					
						
							|  |  |  |   common_length = sind = 0; | 
					
						
							|  |  |  |   if (_rl_completion_prefix_display_length > 0) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       t = printable_part (matches[0]); | 
					
						
							|  |  |  |       temp = strrchr (t, '/'); | 
					
						
							|  |  |  |       common_length = temp ? fnwidth (temp) : fnwidth (t); | 
					
						
							|  |  |  |       sind = temp ? strlen (temp) : strlen (t); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (common_length > _rl_completion_prefix_display_length && common_length > ELLIPSIS_LEN) | 
					
						
							|  |  |  | 	max -= common_length - ELLIPSIS_LEN; | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  | 	common_length = sind = 0; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   /* How many items of MAX length can we fit in the screen window? */ | 
					
						
							|  |  |  |   max += 2; | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |   limit = _rl_screenwidth / max; | 
					
						
							|  |  |  |   if (limit != 1 && (limit * max == _rl_screenwidth)) | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |     limit--; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |   /* Avoid a possible floating exception.  If max > _rl_screenwidth,
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |      limit will be 0 and a divide-by-zero fault will result. */ | 
					
						
							|  |  |  |   if (limit == 0) | 
					
						
							|  |  |  |     limit = 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* How many iterations of the printing loop? */ | 
					
						
							|  |  |  |   count = (len + (limit - 1)) / limit; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   /* Watch out for special case.  If LEN is less than LIMIT, then
 | 
					
						
							|  |  |  |      just do the inner printing loop. | 
					
						
							|  |  |  | 	   0 < len <= limit  implies  count = 1. */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* Sort the items if they are not already sorted. */ | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |   if (rl_ignore_completion_duplicates == 0 && rl_sort_completion_matches) | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |     qsort (matches + 1, len, sizeof (char *), (QSFUNC *)_rl_qsort_string_compare); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |   rl_crlf (); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   lines = 0; | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |   if (_rl_print_completions_horizontally == 0) | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |       /* Print the sorted items, up-and-down alphabetically, like ls. */ | 
					
						
							|  |  |  |       for (i = 1; i <= count; i++) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | 	  for (j = 0, l = i; j < limit; j++) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	    { | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | 	      if (l > len || matches[l] == 0) | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	      else | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 		  temp = printable_part (matches[l]); | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | 		  printed_len = print_filename (temp, matches[l], sind); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | 		  if (j + 1 < limit) | 
					
						
							|  |  |  | 		    for (k = 0; k < max - printed_len; k++) | 
					
						
							|  |  |  | 		      putc (' ', rl_outstream); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	      l += count; | 
					
						
							|  |  |  | 	    } | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | 	  rl_crlf (); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 	  lines++; | 
					
						
							|  |  |  | 	  if (_rl_page_completions && lines >= (_rl_screenheight - 1) && i < count) | 
					
						
							|  |  |  | 	    { | 
					
						
							|  |  |  | 	      lines = _rl_internal_pager (lines); | 
					
						
							|  |  |  | 	      if (lines < 0) | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	    } | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       /* Print the sorted items, across alphabetically, like ls -x. */ | 
					
						
							|  |  |  |       for (i = 1; matches[i]; i++) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  temp = printable_part (matches[i]); | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | 	  printed_len = print_filename (temp, matches[i], sind); | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | 	  /* Have we reached the end of this line? */ | 
					
						
							|  |  |  | 	  if (matches[i+1]) | 
					
						
							|  |  |  | 	    { | 
					
						
							|  |  |  | 	      if (i && (limit > 1) && (i % limit) == 0) | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 		{ | 
					
						
							|  |  |  | 		  rl_crlf (); | 
					
						
							|  |  |  | 		  lines++; | 
					
						
							|  |  |  | 		  if (_rl_page_completions && lines >= _rl_screenheight - 1) | 
					
						
							|  |  |  | 		    { | 
					
						
							|  |  |  | 		      lines = _rl_internal_pager (lines); | 
					
						
							|  |  |  | 		      if (lines < 0) | 
					
						
							|  |  |  | 			return; | 
					
						
							|  |  |  | 		    } | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | 	      else | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 		for (k = 0; k < max - printed_len; k++) | 
					
						
							|  |  |  | 		  putc (' ', rl_outstream); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	    } | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |       rl_crlf (); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											1999-02-19 17:11:39 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Display MATCHES, a list of matching filenames in argv format.  This
 | 
					
						
							|  |  |  |    handles the simple case -- a single match -- first.  If there is more | 
					
						
							|  |  |  |    than one match, we compute the number of strings in the list and the | 
					
						
							|  |  |  |    length of the longest string, which will be needed by the display | 
					
						
							|  |  |  |    function.  If the application wants to handle displaying the list of | 
					
						
							|  |  |  |    matches itself, it sets RL_COMPLETION_DISPLAY_MATCHES_HOOK to the | 
					
						
							|  |  |  |    address of a function, and we just call it.  If we're handling the | 
					
						
							|  |  |  |    display ourselves, we just call rl_display_match_list.  We also check | 
					
						
							|  |  |  |    that the list of matches doesn't exceed the user-settable threshold, | 
					
						
							|  |  |  |    and ask the user if he wants to see the list if there are more matches | 
					
						
							|  |  |  |    than RL_COMPLETION_QUERY_ITEMS. */ | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | display_matches (matches) | 
					
						
							|  |  |  |      char **matches; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   int len, max, i; | 
					
						
							|  |  |  |   char *temp; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* Move to the last visible line of a possibly-multiple-line command. */ | 
					
						
							|  |  |  |   _rl_move_vert (_rl_vis_botlin); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* Handle simple case first.  What if there is only one answer? */ | 
					
						
							|  |  |  |   if (matches[1] == 0) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       temp = printable_part (matches[0]); | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |       rl_crlf (); | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |       print_filename (temp, matches[0], 0); | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |       rl_crlf (); | 
					
						
							| 
									
										
										
										
											1999-02-19 17:11:39 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |       rl_forced_update_display (); | 
					
						
							|  |  |  |       rl_display_fixed = 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* There is more than one answer.  Find out how many there are,
 | 
					
						
							|  |  |  |      and find the maximum printed length of a single entry. */ | 
					
						
							|  |  |  |   for (max = 0, i = 1; matches[i]; i++) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       temp = printable_part (matches[i]); | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |       len = fnwidth (temp); | 
					
						
							| 
									
										
										
										
											1999-02-19 17:11:39 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |       if (len > max) | 
					
						
							|  |  |  | 	max = len; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   len = i - 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* If the caller has defined a display hook, then call that now. */ | 
					
						
							|  |  |  |   if (rl_completion_display_matches_hook) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       (*rl_completion_display_matches_hook) (matches, len, max); | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  |   /* If there are many items, then ask the user if she really wants to
 | 
					
						
							|  |  |  |      see them all. */ | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |   if (rl_completion_query_items > 0 && len >= rl_completion_query_items) | 
					
						
							| 
									
										
										
										
											1999-02-19 17:11:39 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |       rl_crlf (); | 
					
						
							| 
									
										
										
										
											1999-02-19 17:11:39 +00:00
										 |  |  |       fprintf (rl_outstream, "Display all %d possibilities? (y or n)", len); | 
					
						
							|  |  |  |       fflush (rl_outstream); | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |       if ((completion_y_or_n = get_y_or_n (0)) == 0) | 
					
						
							| 
									
										
										
										
											1999-02-19 17:11:39 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | 	  rl_crlf (); | 
					
						
							| 
									
										
										
										
											1999-02-19 17:11:39 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	  rl_forced_update_display (); | 
					
						
							|  |  |  | 	  rl_display_fixed = 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	  return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   rl_display_match_list (matches, len, max); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   rl_forced_update_display (); | 
					
						
							|  |  |  |   rl_display_fixed = 1; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | static char * | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  | make_quoted_replacement (match, mtype, qc) | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |      char *match; | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |      int mtype; | 
					
						
							|  |  |  |      char *qc;	/* Pointer to quoting character, if any */ | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | { | 
					
						
							|  |  |  |   int should_quote, do_replace; | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |   char *replacement; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* If we are doing completion on quoted substrings, and any matches
 | 
					
						
							|  |  |  |      contain any of the completer_word_break_characters, then auto- | 
					
						
							|  |  |  |      matically prepend the substring with a quote character (just pick | 
					
						
							|  |  |  |      the first one from the list of such) if it does not already begin | 
					
						
							|  |  |  |      with a quote string.  FIXME: Need to remove any such automatically | 
					
						
							|  |  |  |      inserted quote character when it no longer is necessary, such as | 
					
						
							|  |  |  |      if we change the string we are completing on and the new set of | 
					
						
							|  |  |  |      matches don't require a quoted substring. */ | 
					
						
							|  |  |  |   replacement = match; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   should_quote = match && rl_completer_quote_characters && | 
					
						
							|  |  |  | 			rl_filename_completion_desired && | 
					
						
							|  |  |  | 			rl_filename_quoting_desired; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (should_quote) | 
					
						
							| 
									
										
										
										
											1999-02-19 17:11:39 +00:00
										 |  |  |     should_quote = should_quote && (!qc || !*qc || | 
					
						
							|  |  |  | 		     (rl_completer_quote_characters && strchr (rl_completer_quote_characters, *qc))); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   if (should_quote) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       /* If there is a single match, see if we need to quote it.
 | 
					
						
							|  |  |  |          This also checks whether the common prefix of several | 
					
						
							|  |  |  | 	 matches needs to be quoted. */ | 
					
						
							| 
									
										
										
										
											1997-09-22 20:22:27 +00:00
										 |  |  |       should_quote = rl_filename_quote_characters | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | 			? (_rl_strpbrk (match, rl_filename_quote_characters) != 0) | 
					
						
							| 
									
										
										
										
											1997-09-22 20:22:27 +00:00
										 |  |  | 			: 0; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |       do_replace = should_quote ? mtype : NO_MATCH; | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |       /* Quote the replacement, since we found an embedded
 | 
					
						
							|  |  |  | 	 word break character in a potential match. */ | 
					
						
							|  |  |  |       if (do_replace != NO_MATCH && rl_filename_quoting_function) | 
					
						
							|  |  |  | 	replacement = (*rl_filename_quoting_function) (match, do_replace, qc); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |   return (replacement); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | static void | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  | insert_match (match, start, mtype, qc) | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |      char *match; | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |      int start, mtype; | 
					
						
							|  |  |  |      char *qc; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | { | 
					
						
							|  |  |  |   char *replacement; | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |   char oqc; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |   oqc = qc ? *qc : '\0'; | 
					
						
							|  |  |  |   replacement = make_quoted_replacement (match, mtype, qc); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   /* Now insert the match. */ | 
					
						
							|  |  |  |   if (replacement) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       /* Don't double an opening quote character. */ | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |       if (qc && *qc && start && rl_line_buffer[start - 1] == *qc && | 
					
						
							|  |  |  | 	    replacement[0] == *qc) | 
					
						
							|  |  |  | 	start--; | 
					
						
							|  |  |  |       /* If make_quoted_replacement changed the quoting character, remove
 | 
					
						
							|  |  |  | 	 the opening quote and insert the (fully-quoted) replacement. */ | 
					
						
							|  |  |  |       else if (qc && (*qc != oqc) && start && rl_line_buffer[start - 1] == oqc && | 
					
						
							|  |  |  | 	    replacement[0] != oqc) | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	start--; | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |       _rl_replace_text (replacement, start, rl_point - 1); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |       if (replacement != match) | 
					
						
							|  |  |  |         free (replacement); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | /* Append any necessary closing quote and a separator character to the
 | 
					
						
							|  |  |  |    just-inserted match.  If the user has specified that directories | 
					
						
							|  |  |  |    should be marked by a trailing `/', append one of those instead.  The | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |    default trailing character is a space.  Returns the number of characters | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |    appended.  If NONTRIVIAL_MATCH is set, we test for a symlink (if the OS | 
					
						
							|  |  |  |    has them) and don't add a suffix for a symlink to a directory.  A | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |    nontrivial match is one that actually adds to the word being completed. | 
					
						
							|  |  |  |    The variable rl_completion_mark_symlink_dirs controls this behavior | 
					
						
							|  |  |  |    (it's initially set to the what the user has chosen, indicated by the | 
					
						
							|  |  |  |    value of _rl_complete_mark_symlink_dirs, but may be modified by an | 
					
						
							|  |  |  |    application's completion function). */ | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | static int | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | append_to_match (text, delimiter, quote_char, nontrivial_match) | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |      char *text; | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |      int delimiter, quote_char, nontrivial_match; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | { | 
					
						
							|  |  |  |   char temp_string[4], *filename; | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |   int temp_string_index, s; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   struct stat finfo; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   temp_string_index = 0; | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |   if (quote_char && rl_point && rl_completion_suppress_quote == 0 && | 
					
						
							|  |  |  |       rl_line_buffer[rl_point - 1] != quote_char) | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |     temp_string[temp_string_index++] = quote_char; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   if (delimiter) | 
					
						
							|  |  |  |     temp_string[temp_string_index++] = delimiter; | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   else if (rl_completion_suppress_append == 0 && rl_completion_append_character) | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |     temp_string[temp_string_index++] = rl_completion_append_character; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   temp_string[temp_string_index++] = '\0'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (rl_filename_completion_desired) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       filename = tilde_expand (text); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |       s = (nontrivial_match && rl_completion_mark_symlink_dirs == 0) | 
					
						
							|  |  |  | 		? LSTAT (filename, &finfo) | 
					
						
							|  |  |  | 		: stat (filename, &finfo); | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |       if (s == 0 && S_ISDIR (finfo.st_mode)) | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  | 	  if (_rl_complete_mark_directories /* && rl_completion_suppress_append == 0 */) | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 	    { | 
					
						
							|  |  |  | 	      /* This is clumsy.  Avoid putting in a double slash if point
 | 
					
						
							|  |  |  | 		 is at the end of the line and the previous character is a | 
					
						
							|  |  |  | 		 slash. */ | 
					
						
							|  |  |  | 	      if (rl_point && rl_line_buffer[rl_point] == '\0' && rl_line_buffer[rl_point - 1] == '/') | 
					
						
							|  |  |  | 		; | 
					
						
							|  |  |  | 	      else if (rl_line_buffer[rl_point] != '/') | 
					
						
							|  |  |  | 		rl_insert_text ("/"); | 
					
						
							|  |  |  | 	    } | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | #ifdef S_ISLNK
 | 
					
						
							|  |  |  |       /* Don't add anything if the filename is a symlink and resolves to a
 | 
					
						
							|  |  |  | 	 directory. */ | 
					
						
							|  |  |  |       else if (s == 0 && S_ISLNK (finfo.st_mode) && | 
					
						
							|  |  |  | 	       stat (filename, &finfo) == 0 && S_ISDIR (finfo.st_mode)) | 
					
						
							|  |  |  | 	; | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |       else | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 	  if (rl_point == rl_end && temp_string_index) | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	    rl_insert_text (temp_string); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |       free (filename); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |       if (rl_point == rl_end && temp_string_index) | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	rl_insert_text (temp_string); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   return (temp_string_index); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | static void | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  | insert_all_matches (matches, point, qc) | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |      char **matches; | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |      int point; | 
					
						
							|  |  |  |      char *qc; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | { | 
					
						
							|  |  |  |   int i; | 
					
						
							|  |  |  |   char *rp; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   rl_begin_undo_group (); | 
					
						
							|  |  |  |   /* remove any opening quote character; make_quoted_replacement will add
 | 
					
						
							|  |  |  |      it back. */ | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |   if (qc && *qc && point && rl_line_buffer[point - 1] == *qc) | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |     point--; | 
					
						
							|  |  |  |   rl_delete_text (point, rl_point); | 
					
						
							|  |  |  |   rl_point = point; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (matches[1]) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       for (i = 1; matches[i]; i++) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  | 	  rp = make_quoted_replacement (matches[i], SINGLE_MATCH, qc); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	  rl_insert_text (rp); | 
					
						
							|  |  |  | 	  rl_insert_text (" "); | 
					
						
							|  |  |  | 	  if (rp != matches[i]) | 
					
						
							|  |  |  | 	    free (rp); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |       rp = make_quoted_replacement (matches[0], SINGLE_MATCH, qc); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |       rl_insert_text (rp); | 
					
						
							|  |  |  |       rl_insert_text (" "); | 
					
						
							|  |  |  |       if (rp != matches[0]) | 
					
						
							|  |  |  | 	free (rp); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   rl_end_undo_group (); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | void | 
					
						
							|  |  |  | _rl_free_match_list (matches) | 
					
						
							| 
									
										
										
										
											1999-02-19 17:11:39 +00:00
										 |  |  |      char **matches; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   register int i; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   if (matches == 0) | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-02-19 17:11:39 +00:00
										 |  |  |   for (i = 0; matches[i]; i++) | 
					
						
							|  |  |  |     free (matches[i]); | 
					
						
							|  |  |  |   free (matches); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | /* Complete the word at or before point.
 | 
					
						
							|  |  |  |    WHAT_TO_DO says what to do with the completion. | 
					
						
							|  |  |  |    `?' means list the possible completions. | 
					
						
							|  |  |  |    TAB means do standard completion. | 
					
						
							|  |  |  |    `*' means insert all of the possible completions. | 
					
						
							|  |  |  |    `!' means to do standard completion, and list all possible completions if | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |    there is more than one. | 
					
						
							|  |  |  |    `@' means to do standard completion, and list all possible completions if | 
					
						
							|  |  |  |    there is more than one and partial completion is not possible. */ | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | int | 
					
						
							|  |  |  | rl_complete_internal (what_to_do) | 
					
						
							|  |  |  |      int what_to_do; | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |   char **matches; | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |   rl_compentry_func_t *our_func; | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |   int start, end, delimiter, found_quote, i, nontrivial_lcd; | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |   char *text, *saved_line_buffer; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   char quote_char; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |   RL_SETSTATE(RL_STATE_COMPLETING); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   set_completion_defaults (what_to_do); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |   saved_line_buffer = rl_line_buffer ? savestring (rl_line_buffer) : (char *)NULL; | 
					
						
							|  |  |  |   our_func = rl_completion_entry_function | 
					
						
							|  |  |  | 		? rl_completion_entry_function | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | 		: rl_filename_completion_function; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   /* We now look backwards for the start of a filename/variable word. */ | 
					
						
							|  |  |  |   end = rl_point; | 
					
						
							|  |  |  |   found_quote = delimiter = 0; | 
					
						
							|  |  |  |   quote_char = '\0'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (rl_point) | 
					
						
							|  |  |  |     /* This (possibly) changes rl_point.  If it returns a non-zero char,
 | 
					
						
							|  |  |  |        we know we have an open quote. */ | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |     quote_char = _rl_find_completion_word (&found_quote, &delimiter); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   start = rl_point; | 
					
						
							|  |  |  |   rl_point = end; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   text = rl_copy_text (start, end); | 
					
						
							|  |  |  |   matches = gen_completion_matches (text, start, end, our_func, found_quote, quote_char); | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |   /* nontrivial_lcd is set if the common prefix adds something to the word
 | 
					
						
							|  |  |  |      being completed. */ | 
					
						
							|  |  |  |   nontrivial_lcd = matches && strcmp (text, matches[0]) != 0; | 
					
						
							| 
									
										
										
										
											1999-02-19 17:11:39 +00:00
										 |  |  |   free (text); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   if (matches == 0) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |       rl_ding (); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |       FREE (saved_line_buffer); | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |       completion_changed_buffer = 0; | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |       RL_UNSETSTATE(RL_STATE_COMPLETING); | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |       _rl_reset_completion_state (); | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |       return (0); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-02-19 17:11:39 +00:00
										 |  |  |   /* If we are matching filenames, the attempted completion function will
 | 
					
						
							|  |  |  |      have set rl_filename_completion_desired to a non-zero value.  The basic | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |      rl_filename_completion_function does this. */ | 
					
						
							| 
									
										
										
										
											1999-02-19 17:11:39 +00:00
										 |  |  |   i = rl_filename_completion_desired; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (postprocess_matches (&matches, i) == 0) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |       rl_ding (); | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |       FREE (saved_line_buffer); | 
					
						
							| 
									
										
										
										
											1999-02-19 17:11:39 +00:00
										 |  |  |       completion_changed_buffer = 0; | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |       RL_UNSETSTATE(RL_STATE_COMPLETING); | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |       _rl_reset_completion_state (); | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |       return (0); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   switch (what_to_do) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |     case TAB: | 
					
						
							|  |  |  |     case '!': | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  |     case '@': | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |       /* Insert the first match with proper quoting. */ | 
					
						
							|  |  |  |       if (*matches[0]) | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  | 	insert_match (matches[0], start, matches[1] ? MULT_MATCH : SINGLE_MATCH, "e_char); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |       /* If there are more matches, ring the bell to indicate.
 | 
					
						
							|  |  |  | 	 If we are in vi mode, Posix.2 says to not ring the bell. | 
					
						
							|  |  |  | 	 If the `show-all-if-ambiguous' variable is set, display | 
					
						
							|  |  |  | 	 all the matches immediately.  Otherwise, if this was the | 
					
						
							|  |  |  | 	 only match, and we are hacking files, check the file to | 
					
						
							|  |  |  | 	 see if it was a directory.  If so, and the `mark-directories' | 
					
						
							|  |  |  | 	 variable is set, add a '/' to the name.  If not, and we | 
					
						
							|  |  |  | 	 are at the end of the line, then add a space.  */ | 
					
						
							|  |  |  |       if (matches[1]) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  if (what_to_do == '!') | 
					
						
							|  |  |  | 	    { | 
					
						
							|  |  |  | 	      display_matches (matches); | 
					
						
							|  |  |  | 	      break; | 
					
						
							|  |  |  | 	    } | 
					
						
							| 
									
										
										
										
											2004-07-27 13:29:18 +00:00
										 |  |  | 	  else if (what_to_do == '@') | 
					
						
							|  |  |  | 	    { | 
					
						
							|  |  |  | 	      if (nontrivial_lcd == 0) | 
					
						
							|  |  |  | 		display_matches (matches); | 
					
						
							|  |  |  | 	      break; | 
					
						
							|  |  |  | 	    } | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	  else if (rl_editing_mode != vi_mode) | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | 	    rl_ding ();	/* There are other matches remaining. */ | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  |       else | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | 	append_to_match (matches[0], delimiter, quote_char, nontrivial_lcd); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     case '*': | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |       insert_all_matches (matches, start, "e_char); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |       break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     case '?': | 
					
						
							|  |  |  |       display_matches (matches); | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     default: | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |       _rl_ttymsg ("bad value %d for what_to_do in rl_complete", what_to_do); | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |       rl_ding (); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |       FREE (saved_line_buffer); | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |       RL_UNSETSTATE(RL_STATE_COMPLETING); | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |       _rl_reset_completion_state (); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |       return 1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |   _rl_free_match_list (matches); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* Check to see if the line has changed through all of this manipulation. */ | 
					
						
							|  |  |  |   if (saved_line_buffer) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       completion_changed_buffer = strcmp (rl_line_buffer, saved_line_buffer) != 0; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |       free (saved_line_buffer); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |   RL_UNSETSTATE(RL_STATE_COMPLETING); | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |   _rl_reset_completion_state (); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |   return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | /***************************************************************/ | 
					
						
							|  |  |  | /*							       */ | 
					
						
							|  |  |  | /*  Application-callable completion match generator functions  */ | 
					
						
							|  |  |  | /*							       */ | 
					
						
							|  |  |  | /***************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Return an array of (char *) which is a list of completions for TEXT.
 | 
					
						
							|  |  |  |    If there are no completions, return a NULL pointer. | 
					
						
							|  |  |  |    The first entry in the returned array is the substitution for TEXT. | 
					
						
							|  |  |  |    The remaining entries are the possible completions. | 
					
						
							|  |  |  |    The array is terminated with a NULL pointer. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    ENTRY_FUNCTION is a function of two args, and returns a (char *). | 
					
						
							|  |  |  |      The first argument is TEXT. | 
					
						
							|  |  |  |      The second is a state argument; it should be zero on the first call, and | 
					
						
							|  |  |  |      non-zero on subsequent calls.  It returns a NULL pointer to the caller | 
					
						
							|  |  |  |      when there are no more matches. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | char ** | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | rl_completion_matches (text, entry_function) | 
					
						
							|  |  |  |      const char *text; | 
					
						
							|  |  |  |      rl_compentry_func_t *entry_function; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |   /* Number of slots in match_list. */ | 
					
						
							|  |  |  |   int match_list_size; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |   /* The list of matches. */ | 
					
						
							|  |  |  |   char **match_list; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |   /* Number of matches actually found. */ | 
					
						
							|  |  |  |   int matches; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |   /* Temporary string binder. */ | 
					
						
							|  |  |  |   char *string; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   matches = 0; | 
					
						
							|  |  |  |   match_list_size = 10; | 
					
						
							|  |  |  |   match_list = (char **)xmalloc ((match_list_size + 1) * sizeof (char *)); | 
					
						
							|  |  |  |   match_list[1] = (char *)NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   while (string = (*entry_function) (text, matches)) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |       if (matches + 1 == match_list_size) | 
					
						
							|  |  |  | 	match_list = (char **)xrealloc | 
					
						
							|  |  |  | 	  (match_list, ((match_list_size += 10) + 1) * sizeof (char *)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       match_list[++matches] = string; | 
					
						
							|  |  |  |       match_list[matches + 1] = (char *)NULL; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* If there were any matches, then look through them finding out the
 | 
					
						
							|  |  |  |      lowest common denominator.  That then becomes match_list[0]. */ | 
					
						
							|  |  |  |   if (matches) | 
					
						
							|  |  |  |     compute_lcd_of_matches (match_list, matches, text); | 
					
						
							|  |  |  |   else				/* There were no matches. */ | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       free (match_list); | 
					
						
							|  |  |  |       match_list = (char **)NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   return (match_list); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* A completion function for usernames.
 | 
					
						
							|  |  |  |    TEXT contains a partial username preceded by a random | 
					
						
							|  |  |  |    character (usually `~').  */ | 
					
						
							|  |  |  | char * | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | rl_username_completion_function (text, state) | 
					
						
							|  |  |  |      const char *text; | 
					
						
							| 
									
										
										
										
											1999-02-19 17:11:39 +00:00
										 |  |  |      int state; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | #if defined (__WIN32__) || defined (__OPENNT)
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |   return (char *)NULL; | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | #else /* !__WIN32__ && !__OPENNT) */
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |   static char *username = (char *)NULL; | 
					
						
							|  |  |  |   static struct passwd *entry; | 
					
						
							|  |  |  |   static int namelen, first_char, first_char_loc; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   char *value; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   if (state == 0) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |       FREE (username); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |       first_char = *text; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |       first_char_loc = first_char == '~'; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |       username = savestring (&text[first_char_loc]); | 
					
						
							|  |  |  |       namelen = strlen (username); | 
					
						
							|  |  |  |       setpwent (); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  | #if defined (HAVE_GETPWENT)
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |   while (entry = getpwent ()) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       /* Null usernames should result in all users as possible completions. */ | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |       if (namelen == 0 || (STREQN (username, entry->pw_name, namelen))) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	break; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   if (entry == 0) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  | #if defined (HAVE_GETPWENT)
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |       endpwent (); | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |       return ((char *)NULL); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |       value = (char *)xmalloc (2 + strlen (entry->pw_name)); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |       *value = *text; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       strcpy (value + first_char_loc, entry->pw_name); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (first_char == '~') | 
					
						
							|  |  |  | 	rl_filename_completion_desired = 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       return (value); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | #endif /* !__WIN32__ && !__OPENNT */
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | /* Okay, now we write the entry_function for filename completion.  In the
 | 
					
						
							|  |  |  |    general case.  Note that completion in the shell is a little different | 
					
						
							|  |  |  |    because of all the pathnames that must be followed when looking up the | 
					
						
							|  |  |  |    completion for a command. */ | 
					
						
							|  |  |  | char * | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | rl_filename_completion_function (text, state) | 
					
						
							|  |  |  |      const char *text; | 
					
						
							| 
									
										
										
										
											1999-02-19 17:11:39 +00:00
										 |  |  |      int state; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |   static DIR *directory = (DIR *)NULL; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |   static char *filename = (char *)NULL; | 
					
						
							|  |  |  |   static char *dirname = (char *)NULL; | 
					
						
							|  |  |  |   static char *users_dirname = (char *)NULL; | 
					
						
							|  |  |  |   static int filename_len; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   char *temp; | 
					
						
							|  |  |  |   int dirlen; | 
					
						
							|  |  |  |   struct dirent *entry; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* If we don't have any state, then do some initialization. */ | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   if (state == 0) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |       /* If we were interrupted before closing the directory or reading
 | 
					
						
							|  |  |  | 	 all of its contents, close it. */ | 
					
						
							|  |  |  |       if (directory) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  closedir (directory); | 
					
						
							|  |  |  | 	  directory = (DIR *)NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |       FREE (dirname); | 
					
						
							|  |  |  |       FREE (filename); | 
					
						
							|  |  |  |       FREE (users_dirname); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |       filename = savestring (text); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |       if (*text == 0) | 
					
						
							|  |  |  | 	text = "."; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |       dirname = savestring (text); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       temp = strrchr (dirname, '/'); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | #if defined (__MSDOS__)
 | 
					
						
							|  |  |  |       /* special hack for //X/... */ | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |       if (dirname[0] == '/' && dirname[1] == '/' && ISALPHA ((unsigned char)dirname[2]) && dirname[3] == '/') | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |         temp = strrchr (dirname + 3, '/'); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |       if (temp) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  strcpy (filename, ++temp); | 
					
						
							|  |  |  | 	  *temp = '\0'; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  | #if defined (__MSDOS__)
 | 
					
						
							|  |  |  |       /* searches from current directory on the drive */ | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |       else if (ISALPHA ((unsigned char)dirname[0]) && dirname[1] == ':') | 
					
						
							| 
									
										
										
										
											2000-03-17 21:46:59 +00:00
										 |  |  |         { | 
					
						
							|  |  |  |           strcpy (filename, dirname + 2); | 
					
						
							|  |  |  |           dirname[2] = '\0'; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |       else | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 	  dirname[0] = '.'; | 
					
						
							|  |  |  | 	  dirname[1] = '\0'; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |       /* We aren't done yet.  We also support the "~user" syntax. */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       /* Save the version of the directory that the user typed. */ | 
					
						
							|  |  |  |       users_dirname = savestring (dirname); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |       if (*dirname == '~') | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  temp = tilde_expand (dirname); | 
					
						
							|  |  |  | 	  free (dirname); | 
					
						
							|  |  |  | 	  dirname = temp; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |       if (rl_directory_rewrite_hook) | 
					
						
							|  |  |  | 	(*rl_directory_rewrite_hook) (&dirname); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-10-10 14:15:34 +00:00
										 |  |  |       /* The directory completion hook should perform any necessary
 | 
					
						
							|  |  |  | 	 dequoting. */ | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |       if (rl_directory_completion_hook && (*rl_directory_completion_hook) (&dirname)) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  free (users_dirname); | 
					
						
							|  |  |  | 	  users_dirname = savestring (dirname); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2006-10-10 14:15:34 +00:00
										 |  |  |       else if (rl_completion_found_quote && rl_filename_dequoting_function) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  /* delete single and double quotes */ | 
					
						
							|  |  |  | 	  temp = (*rl_filename_dequoting_function) (users_dirname, rl_completion_quote_character); | 
					
						
							|  |  |  | 	  free (users_dirname); | 
					
						
							|  |  |  | 	  users_dirname = temp; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |       directory = opendir (dirname); | 
					
						
							| 
									
										
										
										
											2006-10-10 14:15:34 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |       /* Now dequote a non-null filename. */ | 
					
						
							|  |  |  |       if (filename && *filename && rl_completion_found_quote && rl_filename_dequoting_function) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  /* delete single and double quotes */ | 
					
						
							|  |  |  | 	  temp = (*rl_filename_dequoting_function) (filename, rl_completion_quote_character); | 
					
						
							|  |  |  | 	  free (filename); | 
					
						
							|  |  |  | 	  filename = temp; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |       filename_len = strlen (filename); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       rl_filename_completion_desired = 1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* At this point we should entertain the possibility of hacking wildcarded
 | 
					
						
							|  |  |  |      filenames, like /usr/man/man<WILD>/te<TAB>.  If the directory name | 
					
						
							|  |  |  |      contains globbing characters, then build an array of directories, and | 
					
						
							|  |  |  |      then map over that list while completing. */ | 
					
						
							|  |  |  |   /* *** UNIMPLEMENTED *** */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* Now that we have some state, we can read the directory. */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   entry = (struct dirent *)NULL; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |   while (directory && (entry = readdir (directory))) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |       /* Special case for no filename.  If the user has disabled the
 | 
					
						
							|  |  |  |          `match-hidden-files' variable, skip filenames beginning with `.'. | 
					
						
							|  |  |  | 	 All other entries except "." and ".." match. */ | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |       if (filename_len == 0) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | 	  if (_rl_match_hidden_files == 0 && HIDDEN_FILE (entry->d_name)) | 
					
						
							|  |  |  | 	    continue; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	  if (entry->d_name[0] != '.' || | 
					
						
							|  |  |  | 	       (entry->d_name[1] && | 
					
						
							|  |  |  | 		 (entry->d_name[1] != '.' || entry->d_name[2]))) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	    break; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  /* Otherwise, if these match up to the length of filename, then
 | 
					
						
							|  |  |  | 	     it is a match. */ | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | 	  if (_rl_completion_case_fold) | 
					
						
							|  |  |  | 	    { | 
					
						
							|  |  |  | 	      if ((_rl_to_lower (entry->d_name[0]) == _rl_to_lower (filename[0])) && | 
					
						
							|  |  |  | 		  (((int)D_NAMLEN (entry)) >= filename_len) && | 
					
						
							|  |  |  | 		  (_rl_strnicmp (filename, entry->d_name, filename_len) == 0)) | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	    } | 
					
						
							|  |  |  | 	  else | 
					
						
							|  |  |  | 	    { | 
					
						
							|  |  |  | 	      if ((entry->d_name[0] == filename[0]) && | 
					
						
							|  |  |  | 		  (((int)D_NAMLEN (entry)) >= filename_len) && | 
					
						
							|  |  |  | 		  (strncmp (filename, entry->d_name, filename_len) == 0)) | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	    } | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   if (entry == 0) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     { | 
					
						
							|  |  |  |       if (directory) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  closedir (directory); | 
					
						
							|  |  |  | 	  directory = (DIR *)NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |       if (dirname) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  free (dirname); | 
					
						
							|  |  |  | 	  dirname = (char *)NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |       if (filename) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  free (filename); | 
					
						
							|  |  |  | 	  filename = (char *)NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |       if (users_dirname) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  free (users_dirname); | 
					
						
							|  |  |  | 	  users_dirname = (char *)NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       return (char *)NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       /* dirname && (strcmp (dirname, ".") != 0) */ | 
					
						
							|  |  |  |       if (dirname && (dirname[0] != '.' || dirname[1])) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  if (rl_complete_with_tilde_expansion && *users_dirname == '~') | 
					
						
							|  |  |  | 	    { | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	      dirlen = strlen (dirname); | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | 	      temp = (char *)xmalloc (2 + dirlen + D_NAMLEN (entry)); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	      strcpy (temp, dirname); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	      /* Canonicalization cuts off any final slash present.  We
 | 
					
						
							|  |  |  | 		 may need to add it back. */ | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	      if (dirname[dirlen - 1] != '/') | 
					
						
							|  |  |  | 	        { | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	          temp[dirlen++] = '/'; | 
					
						
							|  |  |  | 	          temp[dirlen] = '\0'; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	        } | 
					
						
							|  |  |  | 	    } | 
					
						
							|  |  |  | 	  else | 
					
						
							|  |  |  | 	    { | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	      dirlen = strlen (users_dirname); | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  | 	      temp = (char *)xmalloc (2 + dirlen + D_NAMLEN (entry)); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	      strcpy (temp, users_dirname); | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | 	      /* Make sure that temp has a trailing slash here. */ | 
					
						
							|  |  |  | 	      if (users_dirname[dirlen - 1] != '/') | 
					
						
							|  |  |  | 		temp[dirlen++] = '/'; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	    } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-02-19 17:11:39 +00:00
										 |  |  | 	  strcpy (temp + dirlen, entry->d_name); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  |       else | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	temp = savestring (entry->d_name); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |       return (temp); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | /* An initial implementation of a menu completion function a la tcsh.  The
 | 
					
						
							|  |  |  |    first time (if the last readline command was not rl_menu_complete), we | 
					
						
							|  |  |  |    generate the list of matches.  This code is very similar to the code in | 
					
						
							|  |  |  |    rl_complete_internal -- there should be a way to combine the two.  Then, | 
					
						
							|  |  |  |    for each item in the list of matches, we insert the match in an undoable | 
					
						
							|  |  |  |    fashion, with the appropriate character appended (this happens on the | 
					
						
							|  |  |  |    second and subsequent consecutive calls to rl_menu_complete).  When we | 
					
						
							|  |  |  |    hit the end of the match list, we restore the original unmatched text, | 
					
						
							|  |  |  |    ring the bell, and reset the counter to zero. */ | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | int | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | rl_old_menu_complete (count, invoking_key) | 
					
						
							|  |  |  |      int count, invoking_key; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |   rl_compentry_func_t *our_func; | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |   int matching_filenames, found_quote; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   static char *orig_text; | 
					
						
							|  |  |  |   static char **matches = (char **)0; | 
					
						
							|  |  |  |   static int match_list_index = 0; | 
					
						
							|  |  |  |   static int match_list_size = 0; | 
					
						
							|  |  |  |   static int orig_start, orig_end; | 
					
						
							|  |  |  |   static char quote_char; | 
					
						
							|  |  |  |   static int delimiter; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* The first time through, we generate the list of matches and set things
 | 
					
						
							|  |  |  |      up to insert them. */ | 
					
						
							|  |  |  |   if (rl_last_func != rl_menu_complete) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       /* Clean up from previous call, if any. */ | 
					
						
							|  |  |  |       FREE (orig_text); | 
					
						
							|  |  |  |       if (matches) | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 	_rl_free_match_list (matches); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |       match_list_index = match_list_size = 0; | 
					
						
							|  |  |  |       matches = (char **)NULL; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |       rl_completion_invoking_key = invoking_key; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |       /* Only the completion entry function can change these. */ | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  |       set_completion_defaults ('%'); | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  |       our_func = rl_menu_completion_entry_function; | 
					
						
							|  |  |  |       if (our_func == 0) | 
					
						
							|  |  |  | 	our_func = rl_completion_entry_function | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | 			? rl_completion_entry_function | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | 			: rl_filename_completion_function; | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |       /* We now look backwards for the start of a filename/variable word. */ | 
					
						
							|  |  |  |       orig_end = rl_point; | 
					
						
							|  |  |  |       found_quote = delimiter = 0; | 
					
						
							|  |  |  |       quote_char = '\0'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (rl_point) | 
					
						
							|  |  |  | 	/* This (possibly) changes rl_point.  If it returns a non-zero char,
 | 
					
						
							|  |  |  | 	   we know we have an open quote. */ | 
					
						
							| 
									
										
										
										
											2002-07-17 14:10:11 +00:00
										 |  |  | 	quote_char = _rl_find_completion_word (&found_quote, &delimiter); | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |       orig_start = rl_point; | 
					
						
							|  |  |  |       rl_point = orig_end; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       orig_text = rl_copy_text (orig_start, orig_end); | 
					
						
							|  |  |  |       matches = gen_completion_matches (orig_text, orig_start, orig_end, | 
					
						
							|  |  |  | 					our_func, found_quote, quote_char); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-02-19 17:11:39 +00:00
										 |  |  |       /* If we are matching filenames, the attempted completion function will
 | 
					
						
							|  |  |  | 	 have set rl_filename_completion_desired to a non-zero value.  The basic | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | 	 rl_filename_completion_function does this. */ | 
					
						
							| 
									
										
										
										
											1999-02-19 17:11:39 +00:00
										 |  |  |       matching_filenames = rl_filename_completion_desired; | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-02-19 17:11:39 +00:00
										 |  |  |       if (matches == 0 || postprocess_matches (&matches, matching_filenames) == 0) | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |     	  rl_ding (); | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  | 	  FREE (matches); | 
					
						
							|  |  |  | 	  matches = (char **)0; | 
					
						
							|  |  |  | 	  FREE (orig_text); | 
					
						
							|  |  |  | 	  orig_text = (char *)0; | 
					
						
							|  |  |  |     	  completion_changed_buffer = 0; | 
					
						
							|  |  |  |           return (0); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       for (match_list_size = 0; matches[match_list_size]; match_list_size++) | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |         ; | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |       /* matches[0] is lcd if match_list_size > 1, but the circular buffer
 | 
					
						
							|  |  |  | 	 code below should take care of it. */ | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |       if (match_list_size > 1 && _rl_complete_show_all) | 
					
						
							|  |  |  | 	display_matches (matches); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |   /* Now we have the list of matches.  Replace the text between
 | 
					
						
							|  |  |  |      rl_line_buffer[orig_start] and rl_line_buffer[rl_point] with | 
					
						
							|  |  |  |      matches[match_list_index], and add any necessary closing char. */ | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |   if (matches == 0 || match_list_size == 0)  | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |       rl_ding (); | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |       FREE (matches); | 
					
						
							|  |  |  |       matches = (char **)0; | 
					
						
							|  |  |  |       completion_changed_buffer = 0; | 
					
						
							|  |  |  |       return (0); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |   match_list_index += count; | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |   if (match_list_index < 0) | 
					
						
							|  |  |  |     match_list_index += match_list_size; | 
					
						
							| 
									
										
										
										
											2005-12-07 14:08:12 +00:00
										 |  |  |   else | 
					
						
							|  |  |  |     match_list_index %= match_list_size; | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-02-19 17:11:39 +00:00
										 |  |  |   if (match_list_index == 0 && match_list_size > 1) | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2001-04-06 19:14:31 +00:00
										 |  |  |       rl_ding (); | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |       insert_match (orig_text, orig_start, MULT_MATCH, "e_char); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |   else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       insert_match (matches[match_list_index], orig_start, SINGLE_MATCH, "e_char); | 
					
						
							| 
									
										
										
										
											2001-11-13 17:56:06 +00:00
										 |  |  |       append_to_match (matches[match_list_index], delimiter, quote_char, | 
					
						
							|  |  |  | 		       strcmp (orig_text, matches[match_list_index])); | 
					
						
							| 
									
										
										
										
											1998-04-17 19:52:44 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   completion_changed_buffer = 1; | 
					
						
							|  |  |  |   return (0); | 
					
						
							| 
									
										
										
										
											1996-08-26 18:22:31 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2009-01-12 13:36:28 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | int | 
					
						
							|  |  |  | rl_menu_complete (count, ignore) | 
					
						
							|  |  |  |      int count, ignore; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   rl_compentry_func_t *our_func; | 
					
						
							|  |  |  |   int matching_filenames, found_quote; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   static char *orig_text; | 
					
						
							|  |  |  |   static char **matches = (char **)0; | 
					
						
							|  |  |  |   static int match_list_index = 0; | 
					
						
							|  |  |  |   static int match_list_size = 0; | 
					
						
							|  |  |  |   static int nontrivial_lcd = 0; | 
					
						
							|  |  |  |   static int full_completion = 0;	/* set to 1 if menu completion should reinitialize on next call */ | 
					
						
							|  |  |  |   static int orig_start, orig_end; | 
					
						
							|  |  |  |   static char quote_char; | 
					
						
							|  |  |  |   static int delimiter; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* The first time through, we generate the list of matches and set things
 | 
					
						
							|  |  |  |      up to insert them. */ | 
					
						
							|  |  |  |   if (rl_last_func != rl_menu_complete || full_completion) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       /* Clean up from previous call, if any. */ | 
					
						
							|  |  |  |       FREE (orig_text); | 
					
						
							|  |  |  |       if (matches) | 
					
						
							|  |  |  | 	_rl_free_match_list (matches); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       match_list_index = match_list_size = 0; | 
					
						
							|  |  |  |       matches = (char **)NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       full_completion = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       /* Only the completion entry function can change these. */ | 
					
						
							|  |  |  |       set_completion_defaults ('%'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       our_func = rl_menu_completion_entry_function; | 
					
						
							|  |  |  |       if (our_func == 0) | 
					
						
							|  |  |  | 	our_func = rl_completion_entry_function | 
					
						
							|  |  |  | 			? rl_completion_entry_function | 
					
						
							|  |  |  | 			: rl_filename_completion_function; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       /* We now look backwards for the start of a filename/variable word. */ | 
					
						
							|  |  |  |       orig_end = rl_point; | 
					
						
							|  |  |  |       found_quote = delimiter = 0; | 
					
						
							|  |  |  |       quote_char = '\0'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (rl_point) | 
					
						
							|  |  |  | 	/* This (possibly) changes rl_point.  If it returns a non-zero char,
 | 
					
						
							|  |  |  | 	   we know we have an open quote. */ | 
					
						
							|  |  |  | 	quote_char = _rl_find_completion_word (&found_quote, &delimiter); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       orig_start = rl_point; | 
					
						
							|  |  |  |       rl_point = orig_end; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       orig_text = rl_copy_text (orig_start, orig_end); | 
					
						
							|  |  |  |       matches = gen_completion_matches (orig_text, orig_start, orig_end, | 
					
						
							|  |  |  | 					our_func, found_quote, quote_char); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       nontrivial_lcd = matches && strcmp (orig_text, matches[0]) != 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       /* If we are matching filenames, the attempted completion function will
 | 
					
						
							|  |  |  | 	 have set rl_filename_completion_desired to a non-zero value.  The basic | 
					
						
							|  |  |  | 	 rl_filename_completion_function does this. */ | 
					
						
							|  |  |  |       matching_filenames = rl_filename_completion_desired; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (matches == 0 || postprocess_matches (&matches, matching_filenames) == 0) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  |     	  rl_ding (); | 
					
						
							|  |  |  | 	  FREE (matches); | 
					
						
							|  |  |  | 	  matches = (char **)0; | 
					
						
							|  |  |  | 	  FREE (orig_text); | 
					
						
							|  |  |  | 	  orig_text = (char *)0; | 
					
						
							|  |  |  |     	  completion_changed_buffer = 0; | 
					
						
							|  |  |  |           return (0); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       for (match_list_size = 0; matches[match_list_size]; match_list_size++) | 
					
						
							|  |  |  |         ; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (match_list_size == 0)  | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  rl_ding (); | 
					
						
							|  |  |  | 	  FREE (matches); | 
					
						
							|  |  |  | 	  matches = (char **)0; | 
					
						
							|  |  |  | 	  match_list_index = 0; | 
					
						
							|  |  |  | 	  completion_changed_buffer = 0; | 
					
						
							|  |  |  | 	  return (0); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       /* matches[0] is lcd if match_list_size > 1, but the circular buffer
 | 
					
						
							|  |  |  | 	 code below should take care of it. */ | 
					
						
							|  |  |  |       if (*matches[0]) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  insert_match (matches[0], orig_start, matches[1] ? MULT_MATCH : SINGLE_MATCH, "e_char); | 
					
						
							|  |  |  | 	  orig_end = orig_start + strlen (matches[0]); | 
					
						
							|  |  |  | 	  completion_changed_buffer = STREQ (orig_text, matches[0]) == 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (match_list_size > 1 && _rl_complete_show_all) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  display_matches (matches); | 
					
						
							|  |  |  | 	  /* If there are so many matches that the user has to be asked
 | 
					
						
							|  |  |  | 	     whether or not he wants to see the matches, menu completion | 
					
						
							|  |  |  | 	     is unwieldy. */ | 
					
						
							|  |  |  | 	  if (rl_completion_query_items > 0 && match_list_size >= rl_completion_query_items) | 
					
						
							|  |  |  | 	    { | 
					
						
							|  |  |  | 	      rl_ding (); | 
					
						
							|  |  |  | 	      FREE (matches); | 
					
						
							|  |  |  | 	      matches = (char **)0; | 
					
						
							|  |  |  | 	      full_completion = 1; | 
					
						
							|  |  |  | 	      return (0); | 
					
						
							|  |  |  | 	    } | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |       else if (match_list_size <= 1) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  append_to_match (matches[0], delimiter, quote_char, nontrivial_lcd); | 
					
						
							|  |  |  | 	  full_completion = 1; | 
					
						
							|  |  |  | 	  return (0); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* Now we have the list of matches.  Replace the text between
 | 
					
						
							|  |  |  |      rl_line_buffer[orig_start] and rl_line_buffer[rl_point] with | 
					
						
							|  |  |  |      matches[match_list_index], and add any necessary closing char. */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (matches == 0 || match_list_size == 0)  | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       rl_ding (); | 
					
						
							|  |  |  |       FREE (matches); | 
					
						
							|  |  |  |       matches = (char **)0; | 
					
						
							|  |  |  |       completion_changed_buffer = 0; | 
					
						
							|  |  |  |       return (0); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   match_list_index += count; | 
					
						
							|  |  |  |   if (match_list_index < 0) | 
					
						
							|  |  |  |     match_list_index += match_list_size; | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     match_list_index %= match_list_size; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (match_list_index == 0 && match_list_size > 1) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       rl_ding (); | 
					
						
							|  |  |  |       insert_match (matches[0], orig_start, MULT_MATCH, "e_char); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       insert_match (matches[match_list_index], orig_start, SINGLE_MATCH, "e_char); | 
					
						
							|  |  |  |       append_to_match (matches[match_list_index], delimiter, quote_char, | 
					
						
							|  |  |  | 		       strcmp (orig_text, matches[match_list_index])); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   completion_changed_buffer = 1; | 
					
						
							|  |  |  |   return (0); | 
					
						
							|  |  |  | } |