
/*
 *  MSCAN.C
 *
 * mscan - Scan directories and return a sorted list of file names,
 *	    one at a time.
 *
 *  This code originally taken from sysdep.c:
 *
 * (C) Copyright 1987 by John Gilmore
 * Copying and use of this program are controlled by the terms of the Free
 * Software Foundation's GNU Emacs General Public License.
 *
 * Amiga Changes Copyright 1988 by William Loftus.  All rights reserved.
 *
 * Rewrite for nlib Copyright 1990 by J. Gregory Noel.	All rights reserved.
 */

#include "news.h"
#include <ctype.h>
#include <getfiles.h>
#include <expand_path.h>

#define GAP	2

extern char *NewsDir;		/* Path to news directory */
static dir_list *files; 	/* List of articles to be examined */
static dir_list *curptr;	/* Pointer to current article */
static char *curgroup;		/* Name of current group */

static int	/* select only files that are purely numeric */
filesel(char *a)
{
	while (*a != '\0') {
		if (!isdigit(*a))
			return 0;
		++a;
	}
	return 1;
}

static int	/* sort based upon the numeric value of the filename */
filecmp(dir_list *a, dir_list *b)
{
	register long i;

	i = atol(a->name + GAP) - atol(b->name + GAP);
	if (i != 0) return i > 0;
	return strcmp(a->name, b->name);
}

void		/* remove files marked for deletion */
free_directory(delart)
int delart;
{
    register dir_list *p;
    register int last;

    last = -1;
    while (p = files) {
	files = p->next;
	if (p->name[0]) {
	    if (delart)
		remove(expand_path(curgroup, p->name + GAP));
	} else if (p->name[1])
	    last = atoi(p->name + GAP);
	else if (last < 0)
	    last = 0;
	free(p);
    }
    if (last >= 0) {
	register FILE *fp;
	if (fp = fopen(expand_path(curgroup, ".read"), "w")) {
	    fprintf(fp, "%d", last);
	    fclose(fp);
	}
    } else if (delart) {
	/* all files were deleted -- try to delete directory */
	remove(expand_path(curgroup, ".next"));
	remove(expand_path(curgroup, ".read"));
	rmdir(curgroup);
    }
    curptr = NULL;
    if (curgroup) {
	free(curgroup);
	curgroup = NULL;
    }
}

int		/* produce a list of articles in the group */
scan_directory(char *dir)
{
	register dir_list *p;
	register int count = 0;
	register FILE *fp;
	int read;
	char name[100], newname[100];
	extern int unpackmail(char *dir, int count);

recurse:
	free_directory(0);
	curgroup = strdup((dir == NULL) ? NewsDir : expand_path(NewsDir, dir));
	if (access(curgroup, 0) == -1) {
		free(curgroup), curgroup = NULL;
		return 0;
	}

	if ((files = getfiles(curgroup, GAP, filesel, filecmp)) == NULL) {
		if (unpackmail(curgroup, 0) > 0) {
			/* return scan_directory(dir); */
			goto recurse;
		}
#ifdef NOTDEF	/* DON'T DELETE THE !#@$#@ DIRECTORY IDIOT  */
		/* no files in directory -- try to delete directory */
		remove(expand_path(curgroup, ".next"));
		remove(expand_path(curgroup, ".read"));
		rmdir(curgroup);
#endif
		return 0;
	}

	read = 0;
	if ((fp = fopen(expand_path(curgroup, ".read"), "r")) != NULL) {
		fscanf(fp, "%d", &read);
		fclose(fp);
	}

	for (p = files; p != NULL; p = p->next) {
		p->name[0] = 0;
		p->name[1] = (atoi(p->name + GAP) <= read);
		sprintf(name, "%s/%s", curgroup, p->name + GAP);
		sprintf(newname, "%s/%d", curgroup, ++count);
		if (strcmp(name, newname) != 0)
			if (rename(name, newname) == 0)
				sprintf(p->name + GAP, "%d", count);
	}

	if (unpackmail(curgroup, count) > count)
		return scan_directory(dir);

	if ((fp = fopen(expand_path(curgroup, ".next"), "w")) != NULL) {
		fprintf(fp, "%d", count + 1);
		fclose(fp);
	}
	return count;
}

char *
first_unread(void)
{
	register dir_list *p;

	for (p = files; p != NULL; p = p->next) {
		if (p->name[1] == 0) {
			curptr = p;
			return p->name + GAP;
		}
	}
	curptr = NULL;
	return NULL;
}

int
unread_count(void)
{
	register dir_list *p;
	register int count = 0;

	for (p = files; p != NULL; p = p->next)
		if (p != curptr && p->name[1] == 0)
			++count;
	return count;
}

char *
goto_article(char *name)
{
	register dir_list *p;

	for (p = files; p != NULL; p = p->next) {
		if (strcmp(p->name + GAP, name) == 0) {
			curptr = p;
			return p->name + GAP;
		}
	}
	curptr = NULL;
	return NULL;
}

char *
get_next_art(void)
{
	if (curptr == NULL)
		curptr = files;
	else
		curptr = curptr->next;
	return (curptr == NULL) ? NULL : curptr->name + GAP;
}

char *
get_prev_art(void)
{
	register dir_list *p;

	if (curptr == NULL)
		return NULL;
	if (curptr == files)
		return curptr->name + GAP;
	for (p = files; p != NULL; p = p->next) {
		if (p->next == curptr) {
			curptr = p;
			return p->name + GAP;
		}
	}
	/* should never get here... */
	curptr = NULL;
	return NULL;
}

void
rewind_arts(void)
{
	register dir_list *p;

	for (p = files; p != NULL; p = p->next)
		if (p->name[0] == 0)
			p->name[1] = 0;
	curptr = NULL;
}

void
mark_cur_art(int flag)
{
	if (curptr != NULL)
		curptr->name[1] = flag;
}

void
del_cur_art(int flag)
{
	if (curptr != NULL)
		curptr->name[0] = flag;
}

void
hold_cur_art(void)
{
	if (curptr != NULL)
		curptr->name[1] = curptr->name[0];
}

#ifdef TEST
#undef TEST
#include "unpackmail.c"
char *NewsDir;

main(int argc, char **argv)
{
	register char *p;

	NewsDir = GetConfigDir(UUNEWS);
	printf("%d articles:\n", scan_directory("mail.test"));
	while ((p = get_next_art()) != NULL)
		printf("%s ", p);
	putchar('\n');
	return 0;
}
#endif
