
/*
 *  ANEWS.C
 *
 *  Copyright 1988 by William Loftus.  All rights reserved.
 *
 *  From William P. Loftus's UUCP0.60 distribution.
 */

#include <dos.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include "log.h"
#include "/version.h"

#define YES	     1
#define NO	     0
#define ON	     scr_inverse_on()
#define OFF	     scr_inverse_off()
#define UL_On	     printf("[4m")
#define UL_Off	     printf("[0m")
#define Clear_eol    printf("\x9bK")
#define Clear_Screen printf("\x9bH\x9bJ")
#define Cr	     printf("\xd")
#define PROG_NAME    "Anews"

#define MAXGROUPS   512

IDENT(".00");

int PageSize;
int current = 0;
int countgroups;
int last[MAXGROUPS];	      /*  Last read articles  */
char **ng;
char *get_next_file();
char fg,bg;
char homedir[128];
char *pager;

void init();
void scan_subjects();
void do_quit();
void do_help1();
void do_help2();
void scr_inverse_on();
void scr_inverse_off();
void InitNewsrc();

char **
GetNewsgroups_Lastread()
{
    FILE *fp;
    char buf[BUFSIZ];
    static char *ng[MAXGROUPS];
    int i;

    if(!(fp=fopen("UUNEWS:newsrc","r"))) {
	printf("Anews: Error.. could not open UUNEWS:newsrc\n");
	printf("Creating file UUNEWS:newsrc from UUCP:Lib/newsgroups.\n");
	InitNewsrc();
	fp=fopen("UUNEWS:newsrc","r");
    }

    for(i=0; i < MAXGROUPS; i++) {
	if (fscanf(fp,"%s %d",&buf,&last[i])==EOF)
	    break;
	ng[i] = malloc(strlen(buf));
	strcpy(ng[i],buf);
    }
    fclose(fp);
    countgroups=i;
    return(ng);
}


void
InitNewsrc()
{
    char buffer[80];
    FILE *fp_in, *fp_out;

    if(!(fp_in=fopen("UULIB:newsgroups","r"))) {
	printf("Error:  Cannot open UULIB:newsgroups.\n");
	exit(0);
    }

    if(!(fp_out=fopen("UUNEWS:newsrc","w"))) {
	printf("Error:  Cannot create newsrc file.\n");
	fclose(fp_in);
	exit(0);
    }

    while(fscanf(fp_in,"%s",&buffer)!=EOF) {
	fprintf(fp_out,"%s %d\n",buffer,0);
	strset(buffer,NULL);
    }

    fclose(fp_in); fclose(fp_out);
}

void
main(argc,argv)
int argc;
char **argv;
{
    int ch;

    LogProgram = "ANews";
    init();
    ng = GetNewsgroups_Lastread();
    raw(stdin);
    for (;;) {
	chdir("UUNEWS:");
	do {
	    chdir(ng[current]);
	    if (read_directory() != NULL) {
		ON;
		printf("Read %s? [y/n]",ng[current]);
		OFF;
	    } else {
		if (ng[++current] == NULL)
		    do_quit();
		ch = NULL;
		break;
	    }
	    putchar(' ');
	    ch = getchar();
	    printf("\n");
	} while ((ch == '\n') || (ch == '\r'));

	switch (ch) {
	case 'Y':   /* Force the newsgroup to be read from the start..
		     * We don't want to reset the last message read, so discard
		     * the return
		     */
	    (void)readgroup(ng[current],last[current],1);
	    break;
	case 'y':
	    last[current] = readgroup(ng[current],last[current],0);
	    break;
	case 'n':
	case 'N':
	    if (ng[++current] == NULL)
		do_quit();
	    break;
	case 'h':
	case 'H':
	case '?':
	    do_help1();
	    break;
	case 'q':
	case 'Q':
	    do_quit();
	case '=':
	    read_directory(NULL);
	    scan_subjects();
	    break;
	default:
	    break;
	}
    }
}

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

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

    return(eptr);
}

void
init()
{
    getcwd(homedir, 128);
    chdir("UUNEWS:");
    pager = Get_Env("PAGER", "Sys:Utilities/More");
    fg = *Get_Env("FG","8");
    bg = *Get_Env("BG","0");
    PageSize = atoi(Get_Env("PAGESIZE", "20"));
}

char *
subs(newsfile)
char *newsfile;
{
    FILE *fp;
    int j = 0;
    static char buf[BUFSIZ];

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

    fclose(fp);
    return NULL;
}

void
scan_subjects()
{
    char *ptr,ch,*s;
    int i,pos;
    extern int file_pointer;

    pos = file_pointer;

    i = 0;
    while (ptr = get_next_file()) {
	if (atoi(ptr) == 0)
	    continue;
	if ((++i % PageSize) == 0) {
	    ON;
	    printf("(Hit any key to continue)");
	    OFF;
	    ch=getchar();
	    Cr;
	    Clear_eol;
	    if (ch == 'q')
		break;
	}
	if (s = subs(ptr))
	    printf("%s: %s\n",ptr,s);
	else
	    printf("Error: No Subject line in %s\n",ptr);
    }
    file_pointer = pos;
}

void
do_quit()
{
    FILE *fp;
    int j;


    if(!(fp=fopen("UUNEWS:newsrc","w"))) {
	printf("Error, could not open UUNEWS:newsrc for writing.\n");
    } else {
	for(j = 0; j < countgroups; j++) {
	    fprintf(fp,"%s %d\n",ng[j],last[j]);
	}
    }
    fclose(fp);

    chdir(homedir);
    cooked(stdin);
    exit(0);
}

void
do_help1()
{
    printf("[0;1;33;40m");
    printf("Y      Read this newsgroup\n");
    printf("y      Read only new articles in this newsgroup\n");
    printf("n/N    Skip this newsgroup\n");
    printf("=      List article subjects in this newsgroup\n");
    printf("h/H/?  Display help\n");
    printf("q/Q    Quit to DOS\n");
    printf("[0;31;40m");
}

void
do_help2()
{
    printf("[0;1;33;40m");
    printf("\n(space)   Display next page of current article\n");
    printf("(return)  Same as (space)\n");
    printf("n/N       Goto the next article\n");
    printf("=         List article subjects for the remaining articles\n");
    printf("d/D       Delete this article\n");
    printf("-         Backup to previous article\n");
    printf("^         Goto the first article (sorry no $)\n");
    printf("(number)  Goto the given article number\n");
    printf("./>       Scan subject of next article, hit return to read it\n");
    printf(",/<       Backup one article, displaying its subject\n");
    printf("w/W       Write the current article to a file\n");
    printf("h/H/?     Display help\n");
    printf("q/Q       Quit this group and return to the main menu\n");
    printf("[0;31;40m");
}

readgroup(group,lastread,force)
char *group;
int lastread, force;
{
    char *name;
    FILE *fp;
    char buf[BUFSIZ], newname[40], temp[BUFSIZ];
    int i,done,ch,delete,last2;   /* Can't think of a different way to do it */
    extern int file_pointer;

    if (force==1) {
	file_pointer=0;
	goto Forced;
    }

    while ((atoi(name = get_next_file()) <= lastread) && name);

    if (name == NULL) {
	Clear_Screen;
	printf("\nNo new news articles..\n");
	return (lastread);
    } else
	goto skipit;

    /*
     *	we exit from that pointing to the last file we read..  this gets the
     *	first one we haven't read,   Falling Through CAN be fun ya know?
     */


Forced:
    while(name=get_next_file()) {
skipit:
	/* A necessary little kludge to remember the article number we are on */
	last2=atoi(name);

named_file:
	Clear_Screen;
	if ( (fp = fopen(name,"r")) == NULL) {
	    printf("Article %s unavailable.\n",name);
	    ON;
	    printf("(Hit any key to continue)");
	    OFF;
	    getchar();
	    continue;
	}

	delete = done = NO;
	while (fgets(buf, BUFSIZ, fp) && (*buf != '\n')) {
	    if ((strncmp(buf, "Subject",7) == 0)) {
		fputs("Subject: ", stdout);
		UL_On;
		fputs(buf+9, stdout);
		UL_Off;
	    } else {
		fputs(buf,stdout);
	    }
	}
	do {
	    ON;
	    printf("%s [%s]?",group,name);
	    OFF;
	    putchar(' ');
	    ch = getchar();

	    /* Erase the prompt */
	    Cr;
	    Clear_eol;

	    switch (ch) {
	    case ' ':
	    case '\n':
	    case '\r':
	    case '\t':
		i = 0;
		do {
		    fputs(buf,stdout);
		} while ((fgets(buf,BUFSIZ,fp) != NULL) && ( i++ <PageSize) );
		break;

	    case '?':
	    case 'h':
	    case 'H':
		ON;
		printf("%s [%s]?",group,name);
		OFF;
		do_help2();
		break;

	    case 'w':
	    case 'W':
		ON;
		printf("Write Article %s as ??", name);
		OFF;
		printf(" ");
		strcpy(temp,"copy ");
		strcat(temp,name);
		strcat(temp," to ");
		cooked(stdin);
		gets(newname);
		raw(stdin);
		if (!*newname)
		    break;
		strcat(temp,newname);
		if (system(temp))
		    break;
		printf("%s Saved to %s\n",name,newname);
		break;

	    case '=':
		scan_subjects();
		break;
	    case 'q':
	    case 'Q':
		fclose(fp);
		return(last2>lastread?last2:lastread);
		break;

	    case '-': if (file_pointer != 1)
		file_pointer -= 2;;
		done = YES;
		break;

	    case '^':
		file_pointer = 0;
		done = YES;
		break;

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

	    case '.':
	    case '>':
	    case ',':
	    case '<':
		for(;;) {
		    char *strng;
		    strng=subs(name);
		    strng[strlen(strng)>49?50:strlen(strng)] = NULL;
		    printf("\r             #%-s\t%-50s[K",name,strng);
		    ON;
		    printf("\rGoto Article");
		    OFF;
		    switch (getchar()) {
		    case ',':
		    case '<':
			file_pointer -= 2;
			if (file_pointer <0)
			    file_pointer=0;
		    case '>':
		    case '.':
			name=get_next_file();
			break;
		    default:
			goto named_file;
		    }
		}

	    case 'd':
	    case 'D':
		delete = YES;

	    case 'n':
	    case 'N':
		done = YES;

	    default:
		break;
	    }
	} while (done == NO);

	fclose(fp);
	if (delete == YES) {
	    if (remove(name)) {
		printf("Error deleting %s\n",name);
		ulog(-1, "Error deleting %s", name);
	    }
	}
    }
    return((last2 > lastread) ? last2 : lastread);
}

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

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