1 /* Copyright 1992 Simmule Turner and Rich Salz. All rights reserved.
3 * This software is not subject to any license of the American Telephone
4 * and Telegraph Company or of the Regents of the University of California.
6 * Permission is granted to anyone to use this software for any purpose on
7 * any computer system, and to alter it and redistribute it freely, subject
8 * to the following restrictions:
9 * 1. The authors are not responsible for the consequences of use of this
10 * software, no matter how awful, even if they arise from flaws in it.
11 * 2. The origin of this software must not be misrepresented, either by
12 * explicit claim or by omission. Since few users ever read sources,
13 * credits must appear in the documentation.
14 * 3. Altered versions must be plainly marked as such, and must not be
15 * misrepresented as being the original software. Since few users
16 * ever read sources, credits must appear in the documentation.
17 * 4. This notice may not be removed or altered.
21 ** History and file completion functions for editline library.
24 #include "edit_locl.h"
26 __RCSID("$Heimdal: complete.c 15421 2005-06-16 18:41:28Z lha $"
30 ** strcmp-like sorting predicate for qsort.
33 compare(const void *p1
, const void *p2
)
38 v1
= (char * const *)p1
;
39 v2
= (char * const *)p2
;
40 return strcmp(*v1
, *v2
);
44 ** Fill in *avp with an array of names that match file, up to its length.
48 FindMatches(char *dir
, char *file
, char ***avp
)
58 if ((dp
= opendir(dir
)) == NULL
)
64 while ((ep
= readdir(dp
)) != NULL
) {
66 if (p
[0] == '.' && (p
[1] == '\0' || (p
[1] == '.' && p
[2] == '\0')))
68 if (len
&& strncmp(p
, file
, len
) != 0)
71 if ((ac
% MEM_INC
) == 0) {
72 if ((new = malloc(sizeof(char*) * (ac
+ MEM_INC
))) == NULL
)
75 memcpy(new, av
, ac
* sizeof (char **));
81 if ((av
[ac
] = strdup(p
)) == NULL
) {
89 /* Clean up and return. */
92 qsort(av
, ac
, sizeof (char **), compare
);
97 ** Split a pathname into allocated directory and trailing filename parts.
99 static int SplitPath(char *path
, char **dirpart
, char **filepart
)
101 static char DOT
[] = ".";
105 if ((fpart
= strrchr(path
, '/')) == NULL
) {
106 if ((dpart
= strdup(DOT
)) == NULL
)
108 if ((fpart
= strdup(path
)) == NULL
) {
114 if ((dpart
= strdup(path
)) == NULL
)
116 dpart
[fpart
- path
] = '\0';
117 if ((fpart
= strdup(++fpart
)) == NULL
) {
128 ** Attempt to complete the pathname, returning an allocated copy.
129 ** Fill in *unique if we completed it, or set it to 0 if ambiguous.
133 rl_complete_filename(char *pathname
, int *unique
)
145 ac
= rl_list_possib(pathname
, &av
);
149 s
= strrchr(pathname
, '/');
151 len
= strlen(pathname
);
157 /* Exactly one match -- finish it off. */
159 j
= strlen(av
[0]) - len
+ 2;
160 if ((p
= malloc(j
+ 1)) != NULL
) {
161 memcpy(p
, av
[0] + len
, j
);
162 asprintf(&new, "%s%s", pathname
, p
);
164 rl_add_slash(new, p
, j
+ 1);
172 /* Find largest matching substring. */
173 for (i
= len
, end
= strlen(av
[0]); i
< end
; i
++)
174 for (j
= 1; j
< ac
; j
++)
175 if (av
[0][i
] != av
[j
][i
])
180 if ((p
= malloc(j
)) != NULL
) {
181 memcpy(p
, av
[0] + len
, j
);
188 /* Clean up and return. */
189 for (i
= 0; i
< ac
; i
++)
195 static rl_complete_func_t complete_func
= rl_complete_filename
;
198 rl_complete(char *pathname
, int *unique
)
200 return (*complete_func
)(pathname
, unique
);
204 rl_set_complete_func(rl_complete_func_t func
)
206 rl_complete_func_t old
= complete_func
;
207 complete_func
= func
;
213 ** Return all possible completions.
216 rl_list_possib_filename(char *pathname
, char ***avp
)
222 if (SplitPath(pathname
, &dir
, &file
) < 0)
224 ac
= FindMatches(dir
, file
, avp
);
230 static rl_list_possib_func_t list_possib_func
= rl_list_possib_filename
;
233 rl_list_possib(char *pathname
, char ***avp
)
235 return (*list_possib_func
)(pathname
, avp
);
238 rl_list_possib_func_t
239 rl_set_list_possib_func(rl_list_possib_func_t func
)
241 rl_list_possib_func_t old
= list_possib_func
;
242 list_possib_func
= func
;