3 ** History and file completion functions for editline library.
8 #if defined(NEED_STRDUP)
10 ** Return an allocated copy of a string.
18 if ((new = NEW(char, strlen(p
) + 1)) != NULL
)
22 #endif /* defined(NEED_STRDUP) */
25 ** strcmp-like sorting predicate for qsort.
35 v1
= (CONST
char **)p1
;
36 v2
= (CONST
char **)p2
;
37 return strcmp(*v1
, *v2
);
41 ** Fill in *avp with an array of names that match file, up to its length.
45 FindMatches(dir
, file
, avp
)
59 #define MAX_TOTAL (256 << sizeof(char *))
61 if ((dp
= opendir(dir
)) == NULL
)
69 while ((ep
= readdir(dp
)) != NULL
) {
71 if (p
[0] == '.' && (p
[1] == '\0' || (p
[1] == '.' && p
[2] == '\0')))
73 if (len
&& strncmp(p
, file
, len
) != 0)
77 if ((total
+= strlen(p
)) > MAX_TOTAL
) {
78 /* This is a bit too much. */
79 while (ac
> 0) DISPOSE(av
[--ac
]);
83 if ((ac
% MEM_INC
) == 0) {
84 if ((new = NEW(char*, ac
+ MEM_INC
)) == NULL
) {
89 COPYFROMTO(new, av
, ac
* sizeof (char **));
95 if ((av
[ac
] = strdup(p
)) == NULL
) {
104 /* Clean up and return. */
106 if (total
> MAX_TOTAL
) {
107 char many
[sizeof(total
) * 3];
108 p
= many
+ sizeof(many
);
110 while (choices
> 0) {
111 *--p
= '0' + choices
% 10;
114 while (p
> many
+ sizeof(many
) - 8) *--p
= ' ';
115 if ((p
= strdup(p
)) != NULL
) av
[ac
++] = p
;
116 if ((p
= strdup("choices")) != NULL
) av
[ac
++] = p
;
119 qsort(av
, ac
, sizeof (char **), compare
);
125 ** Split a pathname into allocated directory and trailing filename parts.
128 SplitPath(path
, dirpart
, filepart
)
133 static char DOT
[] = ".";
137 if ((fpart
= strrchr(path
, '/')) == NULL
) {
138 if ((dpart
= strdup(DOT
)) == NULL
)
140 if ((fpart
= strdup(path
)) == NULL
) {
146 if ((dpart
= strdup(path
)) == NULL
)
148 dpart
[fpart
- path
+ 1] = '\0';
149 if ((fpart
= strdup(++fpart
)) == NULL
) {
160 ** Attempt to complete the pathname, returning an allocated copy.
161 ** Fill in *unique if we completed it, or set it to 0 if ambiguous.
164 rl_complete(pathname
, unique
)
179 if (SplitPath(pathname
, &dir
, &file
) < 0)
181 if ((ac
= FindMatches(dir
, file
, &av
)) == 0) {
190 /* Exactly one match -- finish it off. */
192 j
= strlen(av
[0]) - len
+ 2;
193 if ((p
= NEW(char, j
+ 1)) != NULL
) {
194 COPYFROMTO(p
, av
[0] + len
, j
);
195 if ((new = NEW(char, strlen(dir
) + strlen(av
[0]) + 2)) != NULL
) {
196 (void)strcpy(new, dir
);
197 (void)strcat(new, "/");
198 (void)strcat(new, av
[0]);
199 rl_add_slash(new, p
);
207 /* Find largest matching substring. */
208 for (i
= len
, end
= strlen(av
[0]); i
< end
; i
++)
209 for (j
= 1; j
< ac
; j
++)
210 if (av
[0][i
] != av
[j
][i
])
215 if ((p
= NEW(char, j
)) != NULL
) {
216 COPYFROMTO(p
, av
[0] + len
, j
);
223 /* Clean up and return. */
226 for (i
= 0; i
< ac
; i
++)
233 ** Return all possible completions.
236 rl_list_possib(pathname
, avp
)
244 if (SplitPath(pathname
, &dir
, &file
) < 0)
246 ac
= FindMatches(dir
, file
, avp
);
253 * $PchId: complete.c,v 1.3 1996/02/22 21:18:51 philip Exp $