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.
29 ** strcmp-like sorting predicate for qsort.
32 compare(const void *p1
, const void *p2
)
37 v1
= (const char **)p1
;
38 v2
= (const char **)p2
;
39 return strcmp(*v1
, *v2
);
43 ** Fill in *avp with an array of names that match file, up to its length.
47 FindMatches(char *dir
, char *file
, char ***avp
)
57 if ((dp
= opendir(dir
)) == NULL
)
63 while ((ep
= readdir(dp
)) != NULL
) {
65 if (p
[0] == '.' && (p
[1] == '\0' || (p
[1] == '.' && p
[2] == '\0')))
67 if (len
&& strncmp(p
, file
, len
) != 0)
70 if ((ac
% MEM_INC
) == 0) {
71 if ((new = malloc(sizeof(char*) * (ac
+ MEM_INC
))) == NULL
)
74 memcpy(new, av
, ac
* sizeof (char **));
80 if ((av
[ac
] = strdup(p
)) == NULL
) {
88 /* Clean up and return. */
91 qsort(av
, ac
, sizeof (char **), compare
);
96 ** Split a pathname into allocated directory and trailing filename parts.
98 static int SplitPath(char *path
, char **dirpart
, char **filepart
)
100 static char DOT
[] = ".";
104 if ((fpart
= strrchr(path
, '/')) == NULL
) {
105 if ((dpart
= strdup(DOT
)) == NULL
)
107 if ((fpart
= strdup(path
)) == NULL
) {
113 if ((dpart
= strdup(path
)) == NULL
)
115 dpart
[fpart
- path
] = '\0';
116 if ((fpart
= strdup(++fpart
)) == NULL
) {
127 ** Attempt to complete the pathname, returning an allocated copy.
128 ** Fill in *unique if we completed it, or set it to 0 if ambiguous.
132 rl_complete_filename(char *pathname
, int *unique
)
144 ac
= rl_list_possib(pathname
, &av
);
148 s
= strrchr(pathname
, '/');
150 len
= strlen(pathname
);
156 /* Exactly one match -- finish it off. */
158 j
= strlen(av
[0]) - len
+ 2;
159 if ((p
= malloc(j
+ 1)) != NULL
) {
160 memcpy(p
, av
[0] + len
, j
);
161 asprintf(&new, "%s%s", pathname
, p
);
163 rl_add_slash(new, p
);
171 /* Find largest matching substring. */
172 for (i
= len
, end
= strlen(av
[0]); i
< end
; i
++)
173 for (j
= 1; j
< ac
; j
++)
174 if (av
[0][i
] != av
[j
][i
])
179 if ((p
= malloc(j
)) != NULL
) {
180 memcpy(p
, av
[0] + len
, j
);
187 /* Clean up and return. */
188 for (i
= 0; i
< ac
; i
++)
194 static rl_complete_func_t complete_func
= rl_complete_filename
;
197 rl_complete(char *pathname
, int *unique
)
199 return (*complete_func
)(pathname
, unique
);
203 rl_set_complete_func(rl_complete_func_t func
)
205 rl_complete_func_t old
= complete_func
;
206 complete_func
= func
;
212 ** Return all possible completions.
215 rl_list_possib_filename(char *pathname
, char ***avp
)
221 if (SplitPath(pathname
, &dir
, &file
) < 0)
223 ac
= FindMatches(dir
, file
, avp
);
229 static rl_list_possib_func_t list_possib_func
= rl_list_possib_filename
;
232 rl_list_possib(char *pathname
, char ***avp
)
234 return (*list_possib_func
)(pathname
, avp
);
237 rl_list_possib_func_t
238 rl_set_list_possib_func(rl_list_possib_func_t func
)
240 rl_list_possib_func_t old
= list_possib_func
;
241 list_possib_func
= func
;