home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
rtsi.com
/
2014.01.www.rtsi.com.tar
/
www.rtsi.com
/
OS9
/
OSK
/
TELECOM
/
GNU_ATP_1_40.lzh
/
EDITLINE
/
complete.c
next >
Wrap
Text File
|
1993-08-04
|
6KB
|
330 lines
/* $Revision: 1.3 $
**
** History and file completion functions for editline library.
*/
#include "editline.h"
#ifdef __MSDOS__
# ifndef DJD
# include <stdlib.h>
# include <dir.h>
# define FINDFIRST
STATIC int FindMatches ( char *path , char ***avp );
# else
STATIC FindMatches(char *dir, char *file, char ***avp) ;
# endif
#else
# ifdef SYS_OS9
STATIC FindMatches();
# else
STATIC FindMatches(char *dir, char *file, char ***avp) ;
# endif
#endif
#ifdef SYS_OS9
char *rl_complete();
int rl_list_possible();
STATIC int SplitPath();
#else
char *rl_complete ( char *pathname , int *unique );
int rl_list_possib ( char *pathname , char ***avp );
STATIC int SplitPath ( char *path , char **dirpart , char **filepart );
#endif
#ifdef NEED_STRDUP
/*
** Return an allocated copy of a string.
*/
char *strdup(p)
char *p;
{
char *new;
if( ( new = NEW( char, strlen( p ) + 1 ) ) != NULL )
(void) strcpy( new, p );
return( new );
}
#endif /* ifdef NEED_STRDUP */
#ifndef SEPCH
#define SEPCH '/'
#endif
/*
** strcmp-like sorting predicate for qsort.
*/
STATIC int compare(p1, p2)
void *p1;
void *p2;
{
char **v1;
char **v2;
v1 = (char **) p1;
v2 = (char **) p2;
return( strcmp( *v1, *v2 ) );
}
#ifdef FINDFIRST
STATIC int
FindMatches(path, avp)
char *path;
char ***avp;
{
char **av;
char **new;
char *p;
SIZE_T ac;
int i=0 ;
struct ffblk merv ;
av = NULL;
ac = 0;
p = path ;
while(*p) p++, i++ ; /* find proper wild card to append */
if( i > 4)
i = 4 ;
if( i==0 )
i = 1 ;
else
p-- ;
if( *p != '*')
strcat(path, "*") ;
for( ; i > 0 ; i-- ){
if( *p == '.' )
i = -1 ;
else if ( i == 1 )
strcat(path, ".*") ;
else
p-- ;
}
if(!findfirst( (char *) path, &merv, 0 )){
p = merv.ff_name ;
strlwr(p) ;
if ((new = NEW(char*, ac + MEM_INC)) == NULL)
goto myend ;
*avp = new;
av = new ;
if ((av[ac] = strdup(p)) == NULL) {
DISPOSE(av);
goto myend ;
}
ac++;
while( !findnext( &merv )){
p = merv.ff_name ;
strlwr(p);
if ((ac % MEM_INC) == 0) { /* allocate bigger array */
if ((new = NEW(char*, ac + MEM_INC)) == NULL)
goto myend ;
if (ac) {
COPYFROMTO(new, av, ac * sizeof (char **));
DISPOSE(av);
}
*avp = new;
av = new ;
}
if ((av[ac] = strdup(p)) == NULL)
goto myend ;
ac++;
}
}
myend:
if (ac)
qsort(av, ac, sizeof (char **), compare);
return ac;
}
#else
/*
** Fill in *avp with an array of names that match file, up to its length.
** Ignore . and .. .
*/
STATIC FindMatches(dir, file, avp)
char *dir;
char *file;
char ***avp;
{
char **av;
char **new;
char *p;
DIR *dp;
DIRENTRY *ep;
SIZE_T ac;
SIZE_T len;
if ((dp = opendir(dir)) == NULL)
return 0;
av = NULL;
ac = 0;
len = strlen(file);
while ((ep = readdir(dp)) != NULL) {
p = ep->d_name;
if (p[0] == '.' && (p[1] == '\0' || (p[1] == '.' && p[2] == '\0')))
continue;
if (len && strncmp(p, file, len) != 0)
continue;
if ((ac % MEM_INC) == 0) {
if ((new = NEW(char*, ac + MEM_INC)) == NULL)
break;
if (ac) {
COPYFROMTO(new, av, ac * sizeof (char **));
DISPOSE(av);
}
*avp = av = new;
}
if ((av[ac] = strdup(p)) == NULL) {
if (ac == 0)
DISPOSE(av);
break;
}
ac++;
}
/* Clean up and return. */
(void)closedir(dp);
if (ac)
qsort(av, ac, sizeof (char **), compare);
return ac;
}
#endif
/*
** Split a pathname into allocated directory and trailing filename parts.
*/
STATIC int
SplitPath(path, dirpart, filepart)
char *path;
char **dirpart;
char **filepart;
{
static char DOT[] = ".";
char *dpart;
char *fpart;
if ((fpart = strrchr(path, SEPCH )) == NULL) {
if ((dpart = strdup(DOT)) == NULL)
return -1;
if ((fpart = strdup(path)) == NULL) {
DISPOSE(dpart);
return -1;
}
}
else {
if ((dpart = strdup(path)) == NULL)
return -1;
dpart[fpart - path] = '\0';
if ((fpart = strdup(++fpart)) == NULL) {
DISPOSE(dpart);
return -1;
}
}
*dirpart = dpart;
*filepart = fpart;
return 0;
}
/*
** Attempt to complete the pathname, returning an allocated copy.
** Fill in *unique if we completed it, or set it to 0 if ambiguous.
*/
char *
rl_complete(pathname, unique)
char *pathname;
int *unique;
{
char **av;
char *dir;
char *file;
char *new;
char *p;
SIZE_T ac;
SIZE_T end;
SIZE_T i;
SIZE_T j;
SIZE_T len;
if (SplitPath(pathname, &dir, &file) < 0)
return NULL;
#ifndef FINDFIRST
if ((ac = FindMatches(dir, file, &av)) == 0)
#else
if ((ac = FindMatches(pathname, &av)) == 0 )
#endif
{
DISPOSE(dir);
DISPOSE(file);
return NULL;
}
p = NULL;
len = strlen(file);
if (ac == 1) {
/* Exactly one match -- finish it off. */
*unique = 1;
j = strlen(av[0]) - len + 2;
if ((p = NEW(char, j + 1)) != NULL) {
COPYFROMTO(p, av[0] + len, j);
if ((new = NEW(char, strlen(dir) + strlen(av[0]) + 2)) != NULL) {
(void)strcpy(new, dir);
(void)strcat(new, "/");
(void)strcat(new, av[0]);
rl_add_slash(new, p);
DISPOSE(new);
}
}
}
else {
*unique = 0;
if (len) {
/* Find largest matching substring. */
for (i = len, end = strlen(av[0]); i < end; i++)
for (j = 1; j < ac; j++)
if (av[0][i] != av[j][i])
goto breakout;
breakout:
if (i > len) {
j = i - len + 1;
if ((p = NEW(char, j)) != NULL) {
COPYFROMTO(p, av[0] + len, j);
p[j - 1] = '\0';
}
}
}
}
/* Clean up and return. */
DISPOSE(dir);
DISPOSE(file);
for (i = 0; i < ac; i++)
DISPOSE(av[i]);
DISPOSE(av);
return p;
}
/*
** Return all possible completions.
*/
int
rl_list_possib(pathname, avp)
char *pathname;
char ***avp;
{
int ac;
#ifndef FINDFIRST
char *dir;
char *file;
if (SplitPath(pathname, &dir, &file) < 0)
return 0;
ac = FindMatches(dir, file, avp);
DISPOSE(dir);
DISPOSE(file);
#else
ac = FindMatches(pathname, avp);
#endif
return ac;
}