2 ** History and file completion functions for editline library.
7 #if defined(NEED_STRDUP)
9 ** Return an allocated copy of a string.
17 if ((new = NEW(char, strlen(p
) + 1)) != NULL
)
21 #endif /* defined(NEED_STRDUP) */
24 ** strcmp-like sorting predicate for qsort.
34 v1
= (CONST
char **)p1
;
35 v2
= (CONST
char **)p2
;
36 return strcmp(*v1
, *v2
);
40 ** Fill in *avp with an array of names that match file, up to its length.
44 FindMatches(dir
, file
, avp
)
58 #define MAX_TOTAL (256 << sizeof(char *))
60 if ((dp
= opendir(dir
)) == NULL
)
68 while ((ep
= readdir(dp
)) != NULL
) {
70 if (p
[0] == '.' && (p
[1] == '\0' || (p
[1] == '.' && p
[2] == '\0')))
72 if (len
&& strncmp(p
, file
, len
) != 0)
76 if ((total
+= strlen(p
)) > MAX_TOTAL
) {
77 /* This is a bit too much. */
78 while (ac
> 0) DISPOSE(av
[--ac
]);
82 if ((ac
% MEM_INC
) == 0) {
83 if ((new = NEW(char*, ac
+ MEM_INC
)) == NULL
) {
88 COPYFROMTO(new, av
, ac
* sizeof (char **));
94 if ((av
[ac
] = strdup(p
)) == NULL
) {
103 /* Clean up and return. */
105 if (total
> MAX_TOTAL
) {
106 char many
[sizeof(total
) * 3];
107 p
= many
+ sizeof(many
);
109 while (choices
> 0) {
110 *--p
= '0' + choices
% 10;
113 while (p
> many
+ sizeof(many
) - 8) *--p
= ' ';
114 if ((p
= strdup(p
)) != NULL
) av
[ac
++] = p
;
115 if ((p
= strdup("choices")) != NULL
) av
[ac
++] = p
;
118 qsort(av
, ac
, sizeof (char **), compare
);
124 ** Split a pathname into allocated directory and trailing filename parts.
127 SplitPath(path
, dirpart
, filepart
)
132 static char DOT
[] = ".";
136 if ((fpart
= strrchr(path
, '/')) == NULL
) {
137 if ((dpart
= strdup(DOT
)) == NULL
)
139 if ((fpart
= strdup(path
)) == NULL
) {
145 if ((dpart
= strdup(path
)) == NULL
)
147 dpart
[fpart
- path
+ 1] = '\0';
148 if ((fpart
= strdup(++fpart
)) == NULL
) {
159 ** Attempt to complete the pathname, returning an allocated copy.
160 ** Fill in *unique if we completed it, or set it to 0 if ambiguous.
163 rl_complete(pathname
, unique
)
178 if (SplitPath(pathname
, &dir
, &file
) < 0)
180 if ((ac
= FindMatches(dir
, file
, &av
)) == 0) {
189 /* Exactly one match -- finish it off. */
191 j
= strlen(av
[0]) - len
+ 1;
192 if ((p
= NEW(char, j
+ 1)) != NULL
) {
193 COPYFROMTO(p
, av
[0] + len
, j
);
194 if ((new = NEW(char, strlen(dir
) + strlen(av
[0]) + 2)) != NULL
) {
195 (void)strcpy(new, dir
);
196 (void)strcat(new, "/");
197 (void)strcat(new, av
[0]);
198 rl_add_slash(new, p
);
206 /* Find largest matching substring. */
207 for (i
= len
, end
= strlen(av
[0]); i
< end
; i
++)
208 for (j
= 1; j
< ac
; j
++)
209 if (av
[0][i
] != av
[j
][i
])
214 if ((p
= NEW(char, j
)) != NULL
) {
215 COPYFROMTO(p
, av
[0] + len
, j
);
222 /* Clean up and return. */
225 for (i
= 0; i
< ac
; i
++)
232 ** Return all possible completions.
235 rl_list_possib(pathname
, avp
)
243 if (SplitPath(pathname
, &dir
, &file
) < 0)
245 ac
= FindMatches(dir
, file
, avp
);
252 * $PchId: complete.c,v 1.3 1996/02/22 21:18:51 philip Exp $