/*
 * This file is provided for unrestricted use
 * provided that this legend is included on all tape media
 * and as a part of the software program in whole or part.  Users
 * may copy or modify this file without charge, but are not authorized to
 * license or distribute it to anyone else except as part of a product
 * or program developed by the user.
 *
 * THIS FILE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
 *
 * This file is provided with no support and without any obligation on the
 * part of Sun Microsystems, Inc. to assist in its use, correction,
 * modification or enhancement.
 *
 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS FILE
 * OR ANY PART THEREOF.
 *
 * In no event will Sun Microsystems, Inc. be liable for any lost revenue
 * or profits or other special, indirect and consequential damages, even
 * if Sun has been advised of the possibility of such damages.
 *
 * Sun Microsystems, Inc.
 * 2550 Garcia Avenue
 * Mountain View, California  94043
 */

#include <X11/Xos.h>
#include <stdio.h>
#include <sys/stat.h>
#include <xview/xview.h>
#include <xview/font.h>
#include <xview/canvas.h>
#include <xview/panel.h>
#include <xview/termsw.h>
#include <xview/text.h>
#include <xview/notice.h>
#include <gfm_ui.h>

#include "xvnews_ui.h"
#include "xvnews.h"
#include "codes.h"

extern struct globals	*Global;

/* Get the subjects for a selected group. */
read_article(ip, num)
xvnews_xvnews_window_objects    *ip;
int num;
{
static	char	command[MAX_COMMAND_LEN], message[MAX_MESSAGE_LEN];
	char	*new, *old;
static	char	*list[MAX_ARTICLES];
	int	first,last,total,count = 0,oldart,artfirst,artlast,killed=0;
	int	status;
	struct	newsrc_node	*curr = NULL;
	struct kill_list	*kills = NULL, *subjectKill(), *killHeaders();

	/* Get us to the selected group and find the available articles. */
	sprintf(command, "GROUP %s", Global->group);
	put_server(command);
	get_server(message, sizeof(message));
	sscanf(message, "%d", &total);
	if (total != OK_GROUP) {
		reconnect_server();
		put_server(command);
		get_server(message, sizeof(message));
		sscanf(message, "%d", &total);
		if (total != OK_GROUP) {
			xvnews_err(ip,"Unable to retrieve %s!\n",Global->group);
			return -1;
		}
	}
	sscanf(message, "%*d%d%d%d", &total, &first, &last);

	for (curr = Global->head; curr != NULL; curr = curr->nextgroup) {
		if (!strcmp(Global->group, curr->newsgroup))
			break;
	}
	curr->last_article = last;
	/* See if the user wants all articles or not. */
	if (!num) {
		/* Check to see if the user hit all articles */
		if (xv_get(ip->articles_list, XV_SHOW, NULL)) {
			/* Get us all articles before the first shown. */
			old =
			  (char *) xv_get(ip->articles_list, PANEL_LIST_STRING,
			 	0, NULL);
			sscanf(old, "%d", &oldart);
			if (oldart == first) {
				xvnews_err(ip, "All articles displayed.\n");
				return -1;
			}
			artfirst = first;
			artlast = oldart - 1;
			generateKillList(curr);
		} else {
			/* Goto group was hit, get all articles. */
			if (last != 0) {
				curr->articles = total;
				artfirst = first;
				artlast = last;
				xv_set(ip->articles_list,
					 PANEL_LIST_DELETE_ROWS, 0,
                 		xv_get(ip->articles_list,
					 PANEL_LIST_NROWS,NULL), NULL);
			} else {
				/* No articles in selected group. */
				xvnews_err(ip, "No articles available in %s!\n",
					 Global->group);
				return (-1);
			}
		}
		xvnews_err(ip, "Retrieving all available articles in %s...\n",
			Global->group);
	} else {
		/* Just retrieve all unread articles. */
		if (curr->artlist == NULL)
			artfirst = curr->last_article - curr->articles + 1;
		else
			artfirst = curr->artlist->last + 1;
		artlast = last;
		if (xv_get(ip->articles_list, PANEL_LIST_NROWS, NULL))
			xv_set(ip->articles_list, PANEL_LIST_DELETE_ROWS, 0,
                 	xv_get(ip->articles_list, PANEL_LIST_NROWS,NULL), NULL);
		generateKillList(curr);
	}
	sprintf(command, "XHDR subject %d-%d", artfirst, artlast);
	/* Issue the command and get the text from the news server. */
	put_server(command);
	xv_set(ip->xvnews_window, FRAME_BUSY, TRUE, NULL);
	get_server(message, sizeof(message));
	sscanf(message, "%d", &status);
	if (status != OK_HEAD) {
		if (status == ERR_COMMAND) {
			printf("XHDR support not available from NNTP server!\n");
			return -1;
		}
		put_server(command);
		get_server(message, sizeof(message));
		sscanf(message, "%d", &status);
		if (status != OK_HEAD)
			return -1;
	}
	while (*message != '.') {
		get_server(message, sizeof(message));
	/* If the string is not '.' malloc some space and copy the article
	   number and subject into the array.
	 */
		if ((strlen(message) != 1) && (message[0] != '.')) {
			if (Global->single == NULL && (Global->kill != NULL || curr->kill != NULL))
				kills = subjectKill(message, curr->kill, kills);
			list[count] = (char *)malloc(SUBJECT_LENGTH + AUTHOR_LENGTH + 3);
			strncpy(list[count], message, SUBJECT_LENGTH + AUTHOR_LENGTH);
			list[count][SUBJECT_LENGTH + AUTHOR_LENGTH] = '\0';
			if (++count > MAX_ARTICLES) {
				xvnews_err(ip, "The max articles that can be read is %d!\n", MAX_ARTICLES);
				while (count)
					free(list[--count]);
				xv_set(ip->xvnews_window, FRAME_BUSY, FALSE, NULL);
				return -1;
			}
		}
	}
	/* Set the last element of the array to NULL. */
	list[count] = NULL;

	/* Get the authors to these articles. */
	getauthorlist(list, artfirst, artlast, -1);

	/* Insert the subjects into the scrolling list */
	xv_set(ip->articles_list, XV_SHOW, FALSE, NULL);
	xv_set(ip->articles_list, PANEL_LIST_INSERT_STRINGS, 0, list, NULL);

	/* Free the subject space that was malloc'd */
	while (count)
		free(list[--count]);

	if (Global->single == NULL && (headerKill(Global->kill) || headerKill(curr->kill))) 
		kills = killHeaders(Global->kill, curr->kill, artfirst, artlast, kills);

	/* Delete any articles already read. */
	if (num && curr->artlist != NULL && curr->artlist->nextart != NULL)
		delete_articles(ip, curr);

	/* Process the kill list */
	if (kills != NULL)
		killed = articleKill(ip, kills);

	clearKills(curr->kill);
	clearKills(Global->kill);
	curr->kill = NULL;
	Global->kill = NULL;

	/* Set up the unread article counter. */
	if (!num && xv_get(ip->articles_list, XV_SHOW, NULL))
		Global->unread += artlast - artfirst;
	else
		Global->unread = xv_get(ip->articles_list, PANEL_LIST_NROWS, NULL);

	if (num && !Global->unread) 
		return 0;

	/* read the first article. */
	new = (char *) xv_get(ip->articles_list, PANEL_LIST_STRING, 0, NULL);
	sscanf(new, "%d", &Global->article);
	xv_set(ip->articles_list, PANEL_LIST_SELECT, 0, TRUE, NULL);
	retrieve_article(ip, Global->article);

	/* Show the scrolling list and reset the frame busy cursor. */
	if (xv_get(ip->articles_list, PANEL_LIST_NROWS, NULL))
		xv_set(ip->articles_list,
		 	PANEL_LIST_FONTS, Global->listfont, NULL, NULL);
	xv_set(ip->groups_list, XV_SHOW, FALSE, NULL);
	xv_set(ip->articles_list, XV_SHOW, TRUE, NULL);
	xv_set(ip->xvnews_window, FRAME_BUSY, FALSE, NULL);
	xv_set(ip->articles_list, PANEL_LIST_SELECT, 0, TRUE, NULL);
	if (killed)
		xvnews_err(ip, "%d %s killed in %s!\n", killed, killed == 1 ? "article":"articles", Global->group);
	return (1);
}

/* Read an article */
retrieve_article(ip, num)
xvnews_xvnews_window_objects    *ip;
int	num;
{
static	char	command[MAX_COMMAND_LEN], article[MAX_ARTICLE_LEN];
	char	new[120], from_line[121], file[80];
	char	*old, *getenv(), *path;
	int	row, response, header = 0;
	FILE	*ifp_out;
static	char	tfile[]="/tmp/.xvnews.file";
	xvnews_props_objects *prp = (xvnews_props_objects *)xv_get(ip->xvnews_window, XV_KEY_DATA, PROPS_POPUP, NULL);
	kill_popup_objects               *kp = (kill_popup_objects *) xv_get(ip->xvnews_window, XV_KEY_DATA, KILL_POPUP, NULL);

	sprintf(file, "%s.%d", tfile, getpid());
	/* Open the temp file. */
	if ((ifp_out = fopen(file, "w")) == NULL) {
		printf("Unable to open temp file %s!\n", file);
		textsw_reset(ip->article_window, 0, 0);
		return;
	}

	memset(new, '\0', 120);
	row = xv_get(ip->articles_list, PANEL_LIST_FIRST_SELECTED, NULL);
	old = (char *)xv_get(ip->articles_list, PANEL_LIST_STRING, row, NULL);
	if (strncmp(&old[strlen(old) - 6], "[read]", 6) &&
	   strncmp(&old[strlen(old) - 6], "[save]", 6)) {
		/* We haven't read this, mark it and decrement the counter. */
		sprintf(new, "%-76.76s [read]", old);
		Global->unread--;
	} else
		strcpy(new, old);
	xvnews_err(ip, "Reading in article %d...\n", num);
	xv_set(ip->xvnews_window, FRAME_BUSY, TRUE, NULL);
	sprintf(command, "HEAD %d", num);
	put_server(command);
	get_server(article, sizeof(article));
	sscanf(article, "%d", &response);
	if (response != OK_HEAD) {
		xv_set(ip->xvnews_window, FRAME_BUSY, FALSE, NULL);

		xvnews_err(ip, "Lost connection to NNTP server! Restoring connection...\n");
		xv_set(ip->xvnews_window, FRAME_BUSY, TRUE, NULL);
		reconnect_server();
		put_server(command);
		get_server(article, sizeof(article));
		sscanf(article, "%d", &response);
		if (response != OK_HEAD) {
			xvnews_err(ip, "Article requested not available!\n");
			textsw_reset(ip->article_window, 0, 0);
			xv_set(ip->xvnews_window, FRAME_BUSY, FALSE, NULL);
			xv_set(ip->articles_list,
				PANEL_LIST_DELETE, row, NULL);
			return;
		}
	}
	header = xv_get(prp->header_select, PANEL_TOGGLE_VALUE, 0, NULL);
	from_line[0] = '\0';
	while(*article != '.') {
		get_server(article, sizeof(article));
		if (!strncmp(article, "From:", 4)) {
			strncpy(from_line, &article[6], 116);
			from_line[strlen(from_line)] = '\0';
			if (strchr(from_line, '(') == NULL)
				strcat(from_line, " ()");
		}
		if (!header) {
			if (!strncmp(article, "From:", 4))
				fprintf(ifp_out, "From %s\n", from_line);
			if ((!strncmp(article, "Subject:", 8) ||
				!strncmp(article, "Date:", 5) ||
				   !strncmp(article, "Newsgroups:", 11)) &&
					strlen(from_line))
					fprintf(ifp_out, "%s\n", article);
		} else {
			if (!strncmp(article, "Path:", 5)) {
				path = (char *)malloc(strlen(article + 1));
				strcpy(path, &article[6]);
			}
			if (!strncmp(article, "From:", 4)) {
				fprintf(ifp_out, "From %s\nPath:%s\n",
					from_line, path);
				free(path);
			}
			if (*article != '.' && strncmp(article, "From:", 4) &&
			   strncmp(article, "Path:", 5))
				fprintf(ifp_out, "%s\n", article);
		}
	}
	fprintf(ifp_out, "\n");
	put_server("BODY");
	get_server(article, sizeof(article));
	sscanf(article, "%d", &response);
	if (response != OK_BODY) {
		xvnews_err(ip, "Article requested not available\n");
		textsw_reset(ip->article_window, 0, 0);
		xv_set(ip->xvnews_window, FRAME_BUSY, FALSE, NULL);
		xv_set(ip->articles_list,
			PANEL_LIST_DELETE, row, NULL);
		return;
	}
	for(;;) {
		get_server(article, sizeof(article));
		if (article[0] == '.' && article[1] == '\0')
			break;
		if (!strncmp(article, "From", 4))
			fprintf(ifp_out, ">%s\n", article);
		else 
			fprintf(ifp_out, "%s\n", *article == '.' ? &article[1]:article);
	}
	fprintf(ifp_out, "\n");
	fclose(ifp_out);
	xv_set(ip->article_window,
		 TEXTSW_READ_ONLY, FALSE,
		 TEXTSW_MEMORY_MAXIMUM, TEXTSW_INFINITY,
		 NULL);
	textsw_reset(ip->article_window, 0, 0);
	xv_set(ip->article_window,
	    TEXTSW_INSERT_FROM_FILE,	file,
	    NULL);
	xv_set(ip->articles_list, 
	    PANEL_LIST_STRING, row,	new,
	    PANEL_LIST_SELECT, row, TRUE,
	    NULL);
	fillKillText(ip, kp);
	xvnews_err(ip, "Currently in %s, %d unread %s\n",
		Global->group, Global->unread, Global->unread == 1 ? "article":"articles");
	xv_set(ip->xvnews_window, FRAME_BUSY, FALSE, NULL);
}

next_article_proc(ip, status)
xvnews_xvnews_window_objects    *ip;
int status;
{
	char	*item;
	int	num = 0, row = 0;

	row = xv_get(ip->articles_list, PANEL_LIST_FIRST_SELECTED, NULL);
	xv_set(ip->articles_list, PANEL_LIST_SELECT, row, FALSE, NULL);
	status ? ++row:--row;
	if (row == -1) {
		item = (char *) xv_get(ip->articles_list, PANEL_LIST_STRING, 0, NULL);
		sscanf(item, "%d", &num);
		if (get_prev(ip, --num, 0) == -1) {
			xvnews_err(ip, "No more articles available!\n");
			return;
		}
		row = 0;
	}

	if (row >= xv_get(ip->articles_list, PANEL_LIST_NROWS, NULL)) {
		if (Global->mode == ARTICLE_MODE)
			update_newsrc(ip, 0);
		groups_set(ip);
	} else {
		xv_set(ip->articles_list, PANEL_LIST_SELECT, row, TRUE, NULL);
		item = (char *)xv_get(ip->articles_list, PANEL_LIST_STRING,
			 row, NULL);
		sscanf(item, "%d", &num);
		Global->article = num;
		retrieve_article(ip, num);
	}
	return;
}

get_prev(ip, num, row)
xvnews_xvnews_window_objects    *ip;
int num;
int	row;
{
	int art, status, nrow = xv_get(ip->articles_list,PANEL_LIST_NROWS,NULL);
	char	command[MAX_COMMAND_LEN], message[MAX_MESSAGE_LEN];
	char	line[SUBJECT_LENGTH + AUTHOR_LENGTH + 2], *old;

	memset(line, '\0', 80);
	sprintf(command, "XHDR subject %d-%d", num, num);
	put_server(command);
	get_server(message, sizeof(message));
	sscanf(message, "%d", &status);
	if (status != OK_HEAD) {
		reconnect_server();
		put_server(command);
		get_server(message, sizeof(message));
		sscanf(message, "%d", &status);
		if (status != OK_HEAD) 
			return -1;
	}
	while (*message != '.') {
		get_server(message, sizeof(message));
		if (message[0] != '.') 
			strncpy(line, message, SUBJECT_LENGTH + AUTHOR_LENGTH);
	}

	if ((int)strlen(line) < 2)
		return -1;

	getauthorlist(line, num, num, row);
	for (row = 0; row < nrow; row++) {
		old = (char *)xv_get(ip->articles_list, PANEL_LIST_STRING, row, NULL);
		sscanf(old, "%d", &art);
		if (art == num) {
			xv_set(ip->articles_list, PANEL_LIST_CLIENT_DATA,
				 row, num, NULL);
			return row;
		}
		if (num < art)
			break;
	}
	xv_set(ip->articles_list,
		 PANEL_LIST_INSERT, row,
		 PANEL_LIST_STRING, row, line, 
		 PANEL_LIST_CLIENT_DATA, row, num,
		 PANEL_LIST_FONT, row, Global->listfont,
		 NULL);
	Global->unread++;
	return row;
}

get_groups(ip, flg)
xvnews_xvnews_window_objects    *ip;
int flg;
{

static	char	*list[MAX_SUBSCRIBED_GROUPS + 1], line[MAX_SUBSCRIBED_GROUPS][80];
static	char	command[MAX_COMMAND_LEN], message[MAX_MESSAGE_LEN];
	int	total, first, last, unread, row = 0, count = 0;
	struct newsrc_node	*curr = Global->head;

	xv_set(ip->xvnews_window, FRAME_BUSY, TRUE, NULL);
	xv_set(ip->groups_list, PANEL_LIST_DELETE_ROWS, 0,
                xv_get(ip->groups_list, PANEL_LIST_NROWS, NULL), NULL);

	for (curr = Global->head; curr != NULL; curr = curr->nextgroup) {
		if (curr->subscribed == SUBSCRIBED) {
			if (flg) {
				sprintf(command, "GROUP %s", curr->newsgroup);
				put_server(command);
				get_server(message, sizeof(message));
				sscanf(message, "%d", &total);
				if (total != OK_GROUP) {
					reconnect_server();
					put_server(command);
					get_server(message, sizeof(message));
					sscanf(message, "%d", &total);
					if (total != OK_GROUP)
						continue;
				}
				last = curr->last_article;
				total = curr->articles;
				sscanf(message, "%*d%d%d%d", &total, &first, &last);
				curr->last_article = last;
				curr->articles = total;
				unread = unread_articles(curr,(last - total) + 1, last);
			} else
				unread = unread_articles(curr,(curr->last_article - curr->articles) + 1, curr->last_article);
			if (unread > 0) {
				if (row == MAX_SUBSCRIBED_GROUPS) {
					list[row] = NULL;
					xv_set(ip->groups_list,
						PANEL_LIST_INSERT_STRINGS,
						count * MAX_SUBSCRIBED_GROUPS,
						list, NULL);
					row = 0;
					count++;
				}
				sprintf(line[row],
					"%-48.48s%-5d total unread articles",
				 		curr->newsgroup, unread);
				list[row] = line[row];
				++row;
			}
		}
	}
	list[row] = NULL;
	xv_set(ip->groups_list,
	 PANEL_LIST_INSERT_STRINGS, MAX_SUBSCRIBED_GROUPS * count, list,
	 NULL);
	xv_set(ip->articles_list, XV_SHOW, FALSE, NULL);
	xv_set(ip->groups_list, XV_SHOW, TRUE, NULL);
	if (xv_get(ip->groups_list, PANEL_LIST_NROWS, NULL))
		xv_set(ip->groups_list,
		 	PANEL_LIST_FONTS, Global->listfont, NULL, NULL);
	xv_set(ip->groups_list, PANEL_LIST_SELECT, 0, TRUE, NULL);
	xv_set(ip->xvnews_window, FRAME_BUSY, FALSE, NULL);
}

unread_proc(ip)
xvnews_xvnews_window_objects    *ip;
{
	char	*old;
	char	line[120];
	int	row, art;

	row = xv_get(ip->articles_list, PANEL_LIST_FIRST_SELECTED, NULL);
	old = (char *) xv_get(ip->articles_list, PANEL_LIST_STRING, row, NULL);
	sscanf(old, "%d", &art);

	if ((int)strlen(old) < 84) {
		sprintf(line, "%-76.76s [unread]", old);
		xv_set(ip->articles_list,
	    		PANEL_LIST_STRING, row, line,
	    		PANEL_LIST_SELECT, row, TRUE,
	    	NULL);
		Global->unread++;
		xvnews_err(ip, "Currently in %s, %d unread %s\n",
			Global->group, Global->unread,
			 Global->unread == 1 ? "article":"articles");
		if (Global->mode == ALL_ARTICLES &&
			!xv_get(ip->articles_list,PANEL_LIST_CLIENT_DATA,row)) {
			struct newsrc_node      *curr = Global->head;
	
			for (; curr != NULL; curr = curr->nextgroup) 
				if (!strcmp(Global->group, curr->newsgroup))
					break;
			if (curr->subscribed == UNSUBSCRIBED)
				return;
			add_unread(curr, art);
			xv_set(ip->mark_unread_butt,PANEL_CLIENT_DATA,1,NULL);
			xv_set(ip->articles_list, PANEL_LIST_CLIENT_DATA, row, 1, NULL);
		}
	}
}

print_article(ip, print)
xvnews_xvnews_window_objects  *ip;
int print;
{
	char	printcommand[256];
	char	*getenv();
	FILE	*lpr_pipe;
	xvnews_props_objects *prp = (xvnews_props_objects *)xv_get(ip->xvnews_window, XV_KEY_DATA, PROPS_POPUP, NULL);

	xvnews_err(ip, "%sing article...\n", print ? "Print":"Filter");
	xv_set(ip->xvnews_window, FRAME_BUSY, TRUE, NULL);
	
	if (print) {
		strcpy(printcommand,(char *)xv_get(prp->print_text, PANEL_VALUE, NULL));
		if (!strlen(printcommand)) {
			sprintf(printcommand, "/usr/bin/lpr");
		}
	} else {
		strcpy(printcommand,(char *)xv_get(prp->filter_text, PANEL_VALUE, NULL));
		if (!strlen(printcommand)) {
			xvnews_err(ip, "No save filter specified!\n");
			xv_set(ip->xvnews_window, FRAME_BUSY, FALSE, NULL);
			return;
		}
	}
	if ((lpr_pipe = popen(printcommand, "w")) == NULL) {
		xvnews_err(ip, "Failed to open printer!\n");
		xv_set(ip->xvnews_window, FRAME_BUSY, FALSE, NULL);
		return;
	}

	if (write_detail_info((Textsw)ip->article_window, lpr_pipe) != 1) {
		xvnews_err(ip, "Printer error!\n");
	}
	pclose(lpr_pipe);
	xv_set(ip->xvnews_window, FRAME_BUSY, FALSE, NULL);
	xvnews_err(ip, "Article %s through \"%s\"\n",
		 print ? "printed":"filtered", printcommand);
}

int
write_detail_info(txt, fptr)
Textsw  *txt;
FILE    *fptr;
{

	int             textsize, next_pos;
	char            *textbuffer;

	xv_set((Textsw)txt, TEXTSW_INSERTION_POINT, TEXTSW_INFINITY, 0);
	textsize= (Textsw_index)xv_get((Textsw)txt, TEXTSW_INSERTION_POINT);
	textbuffer = (char *) malloc(textsize + 1);
	if (textbuffer == NULL) {
		printf("Malloc failed!\n");
		return(-1);
	}
	memset(textbuffer, '\0', textsize);
	next_pos = (Textsw_index) xv_get((Textsw)txt, TEXTSW_CONTENTS, 0,
	    textbuffer, textsize);
	if (next_pos < 1) {
		free(textbuffer);
		return(-1);
	}
	fwrite(textbuffer, textsize, 1, fptr);
	free(textbuffer);
	return(1);
}

int
next_group(ip, forward)
xvnews_xvnews_window_objects    *ip;
int forward;
{
	char	*new;
	int	row, end, nrows;

	row = xv_get(ip->groups_list, PANEL_LIST_FIRST_SELECTED, NULL);
	nrows = xv_get(ip->groups_list, PANEL_LIST_NROWS, NULL);

	if (!forward) {
		if (row)
			--row;
		else
			return -1;
	}

	if (row < 0 || row >= nrows)
		return(-1);
	else {
		xv_set(ip->groups_list, PANEL_LIST_SELECT, row, TRUE, NULL);
		new = (char *)xv_get(ip->groups_list, PANEL_LIST_STRING, row,
			 NULL);
		sscanf(new, "%s%d", Global->group, &end);
		if (end) {
			xvnews_err(ip,
				 "Retrieving %d unread articles from %s...\n",
					end, Global->group);
			switch (read_article(ip, end)) {
                        case 0:
                                catchup_group(ip);
                                groups_set(ip);
                                xvnews_err(ip, "All articles killed!\n");
                                break;
                        case 1:
                                article_set(ip);
                                break;
                        case -1:
                                xv_set(ip->groups_list, PANEL_LIST_DELETE, row, NULL);
                                groups_set(ip);
                                xvnews_err(ip, "No articles available!\n");
                                break;
                        }
			return(row);
		} else
			return(-1);
	}
}

save_article_proc(gfm, file)
gfm_popup_objects       *gfm;
char *file;
{

	char	*old;
	char 	err[160], line[90];
	int	row, new = 1;
	FILE	*ifp_out;
	struct stat statbuf;
	xvnews_xvnews_window_objects    *bp = (xvnews_xvnews_window_objects *) xv_get(xv_get(gfm->popup, XV_OWNER, NULL), XV_KEY_DATA, INSTANCE, NULL);

	if (!stat(file, &statbuf)) {
		sprintf(err, "Appended article to %s\n", file);
		new = 0;
	} else
		sprintf(err, "Saved article to %s\n", file);

	if ((ifp_out = fopen(file, "a")) == NULL) {
		sprintf(err, "Unable to save article to %s!\n", file);
		xvnews_err(bp, err);
		return;
	}

	if (strstr(file, Global->newsdir) != NULL && !new)
		fprintf(ifp_out, "\n");

	if (write_detail_info((Textsw)bp->article_window, ifp_out) != 1) {
		sprintf(err, "Error saving article to %s!\n", file);
		xvnews_err(bp, err);
		return;
	}

	if (strstr(file, Global->newsdir) != NULL)
		fprintf(ifp_out, "\n");

	fclose(ifp_out);
	row = xv_get(bp->articles_list, PANEL_LIST_FIRST_SELECTED, NULL);
	old = (char *)xv_get(bp->articles_list, PANEL_LIST_STRING, row, NULL);
	sprintf(line, "%-76.76s [save]", old);
	xv_set(bp->articles_list, PANEL_LIST_STRING, row, line, NULL);
	xvnews_err(bp, err);
}
