
/*
 *  ANEWS -r rows -c cols -p group
 */

#include "news.h"
#include <ctype.h>
#include <libraries/dos.h>
#include <getfiles.h>

IDENT(".02");

#define ON		scr_inverse_on()
#define OFF		scr_inverse_off()
#define Clear_eol	printf("\x9bK")
#define Clear_Screen	printf("\x9bH\x9bJ")
#define Cr		putchar('\r')
#define PROG_NAME	"Anews"

char *NewsDir;
char fg, bg;

int NumRows = 22;
int NumCols = 77;

dir_list *groups;

void
initgroups(void)
{
    dir_list *gp;
    int len;
    FILE *fp;
    char buf[50];

    if (groups != NULL)
	return;

    if ((fp = openlib("newsgroups")) == NULL) {
	puts("Couldn't open LIB/newsgroups file");
	exit(2);
    }

    gp = (dir_list *)&groups;
    while (fgets(buf, (int)sizeof buf, fp) != NULL) {
	len = strlen(buf) - 1;
	buf[len] = '\0';
	if ((gp->next = (dir_list *)malloc(4 + len + 1)) == NULL) {
	    puts("Malloc failed!");
	    exit(4);
	}
	gp = gp->next;
	strcpy(gp->name, buf);
    }
    gp->next = NULL;

    fclose(fp);
}

static char *
ng(register int i)
{
    register dir_list *gp;
    register int II = i;
    static char *NAME;
    static int I = -1;

    if (i == I)
	return NAME;

    for (gp = (dir_list *)&groups; (gp = gp->next) != NULL; ) {
	if (--i < 0) {
	    I = II;
	    return (NAME = gp->name);
	}
    }
    return NULL;
}

static char *GroupHelp[] = {
    "y/Y    Read this newsgroup (default)",
    "n/N    Skip this newsgroup",
    "-      Go back to previous news group",
    "^      Go back to first news group",
    "=      List article subjects in this newsgroup",
    "p      Post to this news group",
    "h/H/?  Display help",
    "q/Q    Quit to DOS\n",
    0
};

int
main(ac, av)
char **av;
{
    int ch, cnt, nbr;
    char *curgp;
    int found1 = 0;
    int current = -1;
    int old, last = 0;
    short i;
    short notdone = 1;

    for (i = 1; i < ac; ++i) {
	char *ptr = av[i];

	if (*ptr == '-') {
	    ptr += 2;
	    switch(ptr[-1]) {
	    case 'p':
		if (*ptr)
		    reply(0, NULL, ptr);
		else
		    reply(0, NULL, av[++i]);
		notdone = 0;
		break;
	    case 'r':
		if (*ptr)
		    NumRows = atoi(ptr);
		else
		    NumRows = atoi(av[++i]);
		break;
	    case 'c':
		if (*ptr)
		    NumCols = atoi(ptr);
		else
		    NumCols = atoi(av[++i]);
		break;
	    }
	}
    }

    if (notdone == 0) {
	cooked(stdin);
	exit(1);
    }

    init();

    for (;;) {
	NewGroup:
	if ((curgp = ng(++current)) == NULL) {
	    if (!found1) {
		puts("No News, use 'anews -p group' to post new articles");
		do_quit();
	    } else {
		found1 = 0, current = -1;
		continue;
	    }
	}

	while ((nbr = scan_directory(curgp)) != 0) {
	    old = last, last = current;
	    RepeatGroup:
	    Cr, Clear_eol;
	    ON;
	    cnt = unread_count();
	    printf("%d articles in %s (%d unread)? [%s]",
		nbr, curgp, cnt, (cnt == 0) ? "n/y" : "y/n"
	    );
	    OFF;
	    putchar(' ');
	    ch = rawch();
	    if (ch == ' ')
		ch = (cnt == 0) ? 'n' : 'y';

	    switch (ch) {
	    case 'y':
	    case 'Y':
		++found1;
		if (cnt == 0)
		    rewind_arts();
		ch = readgroup(curgp);
		if (ch == 'q')
		    do_quit();
		if (ch == '$')
		    goto NewGroup;
		if (ch)
		    break;
		/* Fall through to... */
	    case 'q':
	    case 'Q':
		putchar('\n');
		do_quit();
	    case 'n':
	    case 'N':
		putchar('\n');
		goto NewGroup;
	    case '^':
		current = -1;
		goto NewGroup;
	    case '-':
		current = old - 1;
		goto NewGroup;
/* FIXME add case to go directly to a specific (named) news group */
	    case 'h':
	    case 'H':
	    case '?':
		do_help(GroupHelp);
		goto RepeatGroup;
	    case '=':
		putchar('\n');
		scan_subjects(curgp);
		goto RepeatGroup;
	    case 'p':
		putchar('\n');
		reply(0, NULL, curgp);
		goto RepeatGroup;
	    }
	}
    }
    return 0;
}

char *
Get_Env(char *envar, char *def)
{
    char *p, *eptr;

    if ((p = getenv(envar)) != NULL) {
	eptr = (char *)malloc(strlen(p) + 1);
	strcpy(eptr, p);
    } else {
	eptr = def;
    }
    return(eptr);
}

void
init()
{
    NewsDir = GetConfigDir(UUNEWS);
    if (access(NewsDir, 0) == -1) {
	printf("FATAL - couldn't access %s\n", NewsDir);
	exit(1);
    }
    fg = *Get_Env("FG", "8");
    bg = *Get_Env("BG", "0");
    initgroups();
}

static char buf[BUFSIZ];

char *
subs(char *newsfile)
{
    FILE *fp;
    int j;

    if ((fp = fopen(newsfile, "r")) == NULL) {
	printf("Couldn't open %s\n", newsfile);
	return(NULL);
    }
    j = 0;
    while ( (j++<50) && (fgets(buf, (int)sizeof buf, fp) != NULL)) {
	if (strncmp("Subject:", buf, 8) == 0) {
	    buf[strlen(buf)-1] = '\0';
	    fclose(fp);
	    return (buf + 8);
	}
    }
    fclose(fp);
    return NULL;
}

void
do_quit(void)
{
    exit(0);
}

void
do_help(char **pp)
{
    printf("\x9bH\x9bJ\033[0;1;33;40m\r");
    do {
	puts(*pp);
    } while (*++pp != NULL);
    printf("\033[0;31;40m");
}

char *
art2file(char *group, char *art)
{
    static char path[128];

    sprintf(path, "%s/%s", expand_path(NewsDir, group), art);
    return path;
}

int
readgroup(char *group)
{
    register int ch;
    register char *name;
    char newname[128];

    while (name = first_unread()) {
	named_art:
	switch (ch = showart(group, name)) {
	case 'd':
	case 'D':
	    del_cur_art(1);
	    /* fall through to... */

	case 'n':
	case 'N':
	    mark_cur_art(1);
	    break;

	case 'q':
	    free_directory(1);
	    return('x');
	case 'Q':
	    free_directory(0);
	    return ('x');

	case '$':
	    free_directory(1);
	    return '$';

	case '-':
	    name = get_prev_art();
	    goto named_art;

	case '^':
	    rewind_arts();
	    break;

	case '0':
	case '1':
	case '2':
	case '3':
	case '4':
	case '5':
	case '6':
	case '7':
	case '8':
	case '9':
	    newname[0] = ch;
	    ON;
	    printf("Goto Article");
	    OFF;
	    printf(" #%c", ch);
	    gets(newname+1);

	    if ((name = goto_article(newname)) == NULL) {
		/* FIXME -- handle illegal article */
		break;	/* DEBUG */
	    }
	    goto named_art;

	case '.':
	case '>':
	case ',':
	case '<':
	    for(;;) {
		printf("\r             #%s\t%-50s", name, subs(art2file(group, name)));
		ON;
		printf("\rGoto Article");
		OFF;
		switch (rawch()) {
		case '>':
		case '.':
		    if ((name = get_next_art()) == NULL) {
			/* wrap around to begining */
			name = get_next_art();
		    }
		    break;
		case ',':
		case '<':
		    name = get_prev_art();
		    break;
		default:
		    goto named_art;
		}
	    }
	default:
	    break;
	}
    }
    return ('n');
}

void
scr_inverse_on(void)
{
    printf("\x9b\x37;3%c;4%cm", fg, bg);
}

void
scr_inverse_off(void)
{
    printf("\x9b\x30;33;40m\033[0m");
}

rawch(void)
{
    register int ch;

    raw(stdin);
    ch = getchar();
    cooked(stdin);
    return (ch);
}

