/*
 *	(c) Copyright 1990, Kim Fabricius Storm.  All rights reserved.
 *
 *	Directory access.
 * 	read file names in directory 'dir' starting with 'prefix'
 */

#include "config.h"
#include "articles.h"
#include "dir.h"


/* dir.c */

static sort_directory __APROTO((register char **f1, register char **f2));


static char dir_path[FILENAME], *dir_tail;

#ifdef HAVE_DIRECTORY

static string_marker str_mark;
static char **completions = NULL;
static char **comp_iterator;
static char **comp_help;

/*
 * list_directory scans the directory twice; first time to find out how
 * many matches there are, and second time to save the names, after
 * sufficient memory have been allocated to store it all.
 */

static int
sort_directory(f1, f2)		/* Used by qsort */
    register char **f1;
    register char **f2;
{
    return strcmp(*f1, *f2);
}

int
list_directory(dir, prefix)
char *dir, *prefix;
{
    DIR *dirp;
    register Direntry *dp;
    register char *cp;
    register char **comp = NULL;
    int pflen = strlen(prefix);
    unsigned count = 0, comp_length = 0;

    if ((dirp = opendir(dir)) == NULL)
	return 0;			/* tough luck */

    mark_str(&str_mark);

    while ((dp = readdir(dirp)) != NULL) {
	cp = dp->d_name;
#ifdef FAKED_DIRECTORY
	if (dp->d_ino == 0) continue;
	cp[14] = NUL;
#endif
	if (*cp == '.' && (cp[1] == '\0' || (cp[1] == '.' && cp[2] == '\0')))
	    continue;
	if (pflen && strncmp(prefix, cp, pflen)) continue;
	if (count == comp_length) {
	    comp_length += 100;
	    completions = resizeobj(completions, char *, comp_length + 1);
	    comp = completions + count;
	}
	strcpy(*comp++ = alloc_str(strlen(cp)), cp);
	count++;
    }
    closedir(dirp);
    if (count == 0) {
	release_str(&str_mark);
	return 0;
    }

    quicksort(completions, count, char *, sort_directory);
    *comp = (char *)0;
    comp_iterator = completions;
    comp_help = completions;

    dir_tail = dir_path;
    while ((*dir_tail++ = *dir++));
    dir_tail[-1] = '/';

    return 1;
}

int
next_directory(buffer, add_slash)
register char *buffer;
int add_slash;
{
    if (*comp_iterator != NULL) {
	strcpy(buffer, *comp_iterator);

	if (add_slash) {
	    strcpy(dir_tail, *comp_iterator);
	    if (file_exist(dir_path, "d"))
		strcat(buffer, "/");
	}
	comp_iterator++;
	return 1;
    }
    close_directory();
    return 0;
}

int
compl_help_directory()
{
    list_completion((char *)NULL);

    if (*comp_help == NULL) comp_help = completions;
    while (*comp_help && list_completion(*comp_help))
	    comp_help++;

    fl;
    return 1;
}

void
close_directory()
{
    if (completions) {
	release_str(&str_mark);
	freeobj(completions);
	completions = NULL;
    }
}

#else

static FILE *dirf;
static int prefix_lgt;

list_directory(dir, prefix)
char *dir, *prefix;
{
    if (prefix[0])
	sprintf(dir_path, "cd %s && echo %s* 2>/dev/null", dir, prefix);
    else
	sprintf(dir_path, "cd %s && ls 2>/dev/null", dir);
    prefix_lgt = strlen(prefix);

    if ((dirf = popen(dir_path, "r")) == NULL) return 0;

    dir_tail = dir_path;
    while (*dir_tail++ = *dir++);
    dir_tail[-1] = '/';

    return 1;
}

next_directory(buffer, add_slash)
char *buffer;
int add_slash;
{
    register char *cp;
    register int c;

    cp = buffer;
    while ((c = getc(dirf)) != EOF && (c != SP) && (c != NL))
	*cp++ = c;

    if (cp != buffer) {
	*cp = NUL;
	if (strcmp(buffer + prefix_lgt, "*")) {

	    if (!add_slash) return 1;

	    strcpy(dir_tail, buffer);
    	    if (file_exist(dir_path, "d")) {
		*cp++ = '/';
		*cp = NUL;
	    }

	    return 1;
	}

    }

    close_directory();
    return 0;
}

compl_help_directory()
{
    return 0;
}

close_directory()
{
    if (dirf) {
	pclose(dirf);
	dirf = NULL;
    }
}
#endif /* HAVE_DIRECTORY */

