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

#include <stdlib.h>
#include <string.h>
#include "config.h"
#include "global.h"
#include "articles.h"
#include "dir.h"
#include "nn_term.h"


/* dir.c */

static int      sort_directory(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(register char **f1, register char **f2)
{				/* Used by qsort */
    return strcmp(*f1, *f2);
}

int
list_directory(char *dir, char *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(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(void)
{
    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(void)
{
    if (completions) {
	release_str(&str_mark);
	freeobj(completions);
	completions = NULL;
    }
}

#else

static FILE    *dirf;
static int      prefix_lgt;

int
list_directory(char *dir, char *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(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;
}

int
compl_help_directory(void)
{
    return 0;
}

void
close_directory(void)
{
    if (dirf) {
	pclose(dirf);
	dirf = NULL;
    }
}

#endif				/* HAVE_DIRECTORY */


syntax highlighted by Code2HTML, v. 0.9.1