
/***************************************************************************
 *   Copyright (C) 1997 to 2004 by Jonathan Duddington                     *
 *   email: jonsd@users.sourceforge.net                                    *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 3 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write see:                           *
 *               <http://www.gnu.org/licenses/>.                           *
 ***************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>

/* Edit: Newsgroups, Mailing Lists
*/

#include "menu.h"
#include "event.h"
#include "template.h"
#include "win.h"
#include "wimp.h"
#include "dbox.h"
#include "werr.h"
#include "wimpt.h"
#include "os.h"
#include "bbc.h"
#include "akbd.h"

#include "narc.h"
#include "hdrs.h"



extern OPTIONS options;
extern FOLDREC src_fr;
extern char *path_choices;
extern BLIST newsglist;
extern BLIST mlistlist;
extern char mbox_list[];
extern int dbox_menu_field;
extern wimp_menustr *wmenu_boxes_names;
extern int transport_opts;

extern int lists_line_height;
extern int lists_font_offset;
extern int standard_font;

extern menu blist_current_menu;
extern int blist_current_menu_line;
extern int blist_current_menu_blist;


/******************************************************************/
/*                    NEWSGROUP MANAGEMENT                        */
/******************************************************************/

static char *err_newsgroups_file = "Can't read Newsgroups file %s.  Try re-selecting Preferences->News->Transport.";
static char *string_users = "(user's sig)";

extern char *err_newsgroups_no_dot;

NEWSG **ng_index;
int  n_ngroups;   /* number of newsgroups and mailing lists */
int  n_ngroups2;  /* number of newsgroups (not mailing lists) */
int  n_ngroups_max;  /* size of ng_index array, including spare space */
int source_count = 0;
dbox dbox_newsg = NULL;
int  dbox_newsg_box;
int  dbox_newsg_default_user;
NEWSG *ng_edit = NULL;
static BLIST *newsg_edit_blist;


static int newsg_back_articles=0;
static NEWSG *newsg_back_articles_ng=NULL;


int newsg_lookup_ix(char *name)
/*****************************/
{
	int i;

	for(i=0; i<n_ngroups; i++)
	{
		if(strcmp_lc(name,ng_index[i]->name)==0)
			return(i);
	}
	return(-1);
}   /* end of newsg_lookup_ix */



void check_newsg_length()
/***********************/
{
	int i;
	int max=0;
	int limit = sizeof(NEWSG)+100;

	for(i=0; i<n_ngroups; i++)
	{
		if(ng_index[i]->length > max)
			max = ng_index[i]->length;
	}
	if(max>=limit)
		werr(0,"Newsgroup entry length error: %d (limit %d)",max,limit);
	return;
}   /* end of newsg_lookup_ix */




int newsg_sorter(const void *p1, const void *p2)
/**********************************************/
{
	int  i;
	NEWSG *n1, *n2;
	char *s1, *s2;
	char buf[150];

	n1 = *(NEWSG **)p1;
	n2 = *(NEWSG **)p2;

	i = (n1->maillist & 1) - (n2->maillist & 1);
	if(i != 0)
		return(i);

	if(n1->maillist & 1)
	{
		strcpy(buf,expand_source(n1->source,3));
		s1 = buf;
	}
	else
	{
		s1 = n1->name;
	}

	if(n2->maillist & 1)
	{
		s2 = expand_source(n2->source,3);
	}
	else
	{
		s2 = n2->name;
	}
	return(strcmp_lc(s1,s2));
}   /* end of newsg_sorter */





void newsg_sort()
/**************/
/* Sort newsgroups ahead of mailing lists */
{
	int  ix;

	qsortG(ng_index,n_ngroups,sizeof(void *),newsg_sorter);

	n_ngroups2 = n_ngroups;
	for(ix=0; ix<n_ngroups; ix++)
	{
		if(ng_index[ix]->maillist)
		{
			n_ngroups2 = ix;
			break;
		}
	}

	newsglist.n_entries = n_ngroups2;
	newsglist.index_ptr = (void **)ng_index;

	mlistlist.n_entries = n_ngroups - n_ngroups2;
	mlistlist.index_ptr = (void **)ng_index;
}   /* end of newsg_sort */




static NEWSG *newsg_alloc(char *name)
/***********************************/
{
	NEWSG *ng;
	int  length;
	int  new_source;

	/* need to allocate a new newsgroup */
	if(!isalnum(name[0]) || !isalnum(name[1]))
		return(NULL);


	if(n_ngroups >= n_ngroups_max)
	{
		n_ngroups_max = n_ngroups + 50;
		realloc(ng_index,n_ngroups_max*sizeof(void *));
	}

	length = (sizeof(NEWSG) + strlen(name) + 3) & ~3;
	ng = calloc(length,1);
	if(ng == NULL)
	{
		malloc_err(40);
		return(NULL);
	}
	ng_index[n_ngroups++] = ng;

	strcpy(ng->name,name);
	ng->length = length;
	ng->box = options.news_box;


	ng->source = category_lookup(&src_fr,name,0);
	if(ng->source == 0)
	{
		/* add this newsgroup to the list of source names */
		source_count += category_add_child(&src_fr,name,"news",&new_source,0);
		ng->source = new_source;
	}
	return(ng);
}   /* end of newsg_alloc */







static void newsg_load_voyager(int control)
/*****************************************/
{
	FILE *f_in;
	int  serial;
	int  active;
	int  n_arts;
	int  ng_num;
	int  voy_x;
	NEWSG *ng;
	int  i;
	char buf[128];
	char path1[180];
	char name[80];

	sprintf(path1,"%s.Groups",options.ngroups_data);
	f_in = fopen_werr(path1,"r",NULL);
	if(f_in != NULL)
	{
		fgets(buf,sizeof(buf),f_in);
		fgets(buf,sizeof(buf),f_in);

		while(!feof(f_in))
		{
			if(fgets(buf,sizeof(buf),f_in)==NULL)
				break;
			i = sscanf(buf,"%d %d %d %d %d %s",&voy_x,&active,&n_arts,&ng_num,&serial,name);

			if(i != 6)
				continue;

			ng = newsg_lookup(name);
			if(ng == NULL)
			{
				/* need to allocate a new newsgroup */
				ng = newsg_alloc(name);
				if(ng == NULL)
					continue;
			}

			ng->serial = serial;
			ng->active = active;
			ng->ng_num = ng_num;
			ng->voy_x = voy_x;
		}
		fclose(f_in);
	}

	/* read serial numbers from Subscribe file */
	sprintf(path1,"%s.Subscribe",options.ngroups_data);
	f_in = fopen(path1,"r");
	if(f_in == NULL)
	{
		werr(0,err_newsgroups_file,path1);
		return;
	}

	while(!feof(f_in))
	{
		if(fgets(buf,sizeof(buf),f_in)==NULL)
			break;
		sscanf(buf,"%s %d",name,&serial);

		ng = newsg_lookup(name);
		if(ng == NULL)
		{
			/* need to allocate a new newsgroup */
			ng = newsg_alloc(name);
			if(ng == NULL)
				continue;
		}
		ng->serial = serial;
		ng->active = 1;
	}

	fclose(f_in);
}   /* end of newsg_load_voyager */







static void newsg_save_voyager()
/******************************/
{
	FILE *f;
	int *pi;
	NEWSG *ng;

	int voy_x;
	int active;
	int n_arts;
	int ng_num;
	int serial;
	int *n_articles;
	int  ix;
	int ng_count;
	char name[80];
	char buf[128];
	char path[180];

	sprintf(path,"%s.Groups",options.ngroups_data);
	n_articles = malloc(n_ngroups*sizeof(int));
	for(ix=0; ix<n_ngroups; ix++)
	{
		n_articles[ix] = -1;  /* until read from the Groups file */
	}

	f = fopen_werr(path,"r","Newsgroups");
	if(f == NULL)
	{
		free(n_articles);
		return;
	}

	fgets(buf,sizeof(buf),f);
	fgets(buf,sizeof(buf),f);

	ng_count = 0;
	while(!feof(f))
	{
		if(fgets(buf,sizeof(buf),f)==NULL)
			break;
		sscanf(buf,"%d %d %d %d %d %s",&voy_x,&active,&n_arts,&ng_num,&serial,name);

		/* read and use voyager-specific data */
		ix = newsg_lookup_ix(name);
		if(ix >= 0)
		{
			ng = ng_index[ix];
			ng->voy_x = voy_x;
			ng->ng_num = ng_num;
			n_articles[ix] = n_arts;
			ng_count++;
		}
	}
	fclose(f);

	f = fopen_werr(path,"w","Newsgroups");
	if(f == NULL)
	{
		free(n_articles);
		return;
	}

	if(ng_count > n_ngroups2)
		ng_count = n_ngroups2;
	fprintf(f,"2\n%d\n",ng_count);

	for(ix=0; ix<n_ngroups2; ix++)
	{
		if(n_articles[ix] < 0)
			continue;    /* didn't find this newsgroup in Voyager's Groups file */

		ng = ng_index[ix];
		if(ng->maillist)
			continue;

		pi = (int *)ng->server;
		fprintf(f,"%d %d %d %d %d %s\n",ng->voy_x,ng->active,n_articles[ix],ng->ng_num,ng->serial,ng->name);
	}
	fclose(f);
	free(n_articles);

	sprintf(buf,"%s.Subscribe",options.ngroups_data);
	f = fopen_werr(buf,"w","Newsgroups");
	if(f == NULL)
		return;

	for(ix=0; ix<n_ngroups2; ix++)
	{
		ng = ng_index[ix];
		if(ng->maillist)
			continue;

		if(ng->active)
		{
			fprintf(f,"%s",ng->name);
			if(ng->serial != -1)
				fprintf(f," %d",ng->serial);
			fprintf(f,"\n");
		}
	}
	fclose(f);

}   /* end of newsg_save_voyager */




void newsg_copy_out(FILE *f_in,FILE *f_out,char *match)
/*****************************************************/
{
	int  length;
	char buf[120];

	length = strlen(match);

	while(!feof(f_in))
	{
		if(fgets(buf,sizeof(buf),f_in)==NULL)
			break;

		if(f_out != NULL)
			fprintf(f_out,"%s",buf);

		if((length > 0) && (memcmp(buf,match,length)==0))
			break;
	}
}   /* end of newsg_copy_out */




static void newsg_save_ant()
/**************************/
{
	FILE *f;
	FILE *f_in;
	int  ix;
	NEWSG *ng;
	char buf[120];
	char path1[180];
	char path2[180];

	sprintf(path1,"%s./active",options.ngroups_data);
	f_in = fopen_werr(path1,"r","Newsgroups");
	if(f_in == NULL)
		return;

	sprintf(path2,"%s1",path1);
	f = fopen_werr(path2,"w",NULL);

	while(!feof(f_in))
	{
		if(fgets(buf,sizeof(buf),f_in)==NULL)
			break;
		if(buf[0] == '#')
			fprintf(f,"%s",buf);
	}
	fclose(f_in);

	for(ix=0; ix<n_ngroups2; ix++)
	{
		ng = ng_index[ix];
		if(ng->maillist)
			continue;

		fprintf(f,"%s %.10d %.10d %c SMAX=0000000000",ng->name,ng->serial,ng->serial2,ng->moderated);
		if(ng->expiry > 0)
			fprintf(f," TIME=%d",ng->expiry);
		if(ng->ng_flags & NG_HEADFETCH)
			fprintf(f," HEADFETCH");
		if(ng->active == 0)
			fprintf(f," NOFETCH");
		fputc('\n',f);
	}
	fclose(f);

	/* rename active1 to active */
	remove(path1);
	rename(path2,path1);
}   /* end of newsg_save_ant */



static void newsg_save_newshound2(char *server)
/*********************************************/
{
	FILE *f;
	FILE *f_in;
	int  ix;
	NEWSG *ng;
	int  serial;
	char path1[180];
	char path2[180];
	char buf[128];
	char name[80];

	sprintf(path1,"%s.%sGroup",options.ngroups_data,server);
	f_in = fopen_werr(path1,"r","Newsgroups");
	if(f_in == NULL)
		return;

	sprintf(path2,"%s1",path1);
	f = fopen_werr(path2,"w",NULL);

	newsg_copy_out(f_in,f,"# Newsgroups:");


	while(!feof(f_in))
	{
		if(fgets(buf,sizeof(buf),f_in)==NULL)
			break;

		serial = -1;
		sscanf(buf,"%s %d",name,&serial);

		ng = newsg_lookup(name);
		if(ng == NULL)
			continue;

		if(serial >= 0)
		{
			ng->serial = serial;
			if(ng == newsg_back_articles_ng)
			{
				if(newsg_back_articles > 0)
					ng->serial = -newsg_back_articles;
			}
		}
	}
	fclose(f_in);


	/* put header only newsgroups after full body newsgroups */
	for(ix=0; ix<n_ngroups2; ix++)
	{
		ng = ng_index[ix];
		if(ng->maillist)
			continue;

		if((!isalpha(ng->server[0]) && (strcmp_lc(server,options.newshound_mnem)==0))
				|| (strcmp_lc(ng->server,server)==0) || (strcmp_lc(ng->server,"all")==0))
		{
			if(((ng->ng_flags & NG_HEADFETCH)==0) && (ng->active))
			{
				fprintf(f,"%s\t%d\n",ng->name,ng->serial);
			}
		}
	}
	for(ix=0; ix<n_ngroups2; ix++)
	{
		ng = ng_index[ix];
		if(ng->maillist)
			continue;

		if((!isalpha(ng->server[0]) && (strcmp_lc(server,options.newshound_mnem)==0))
				|| (strcmp_lc(ng->server,server)==0) || (strcmp_lc(ng->server,"all")==0))
		{
			if((ng->ng_flags & NG_HEADFETCH) && (ng->active))
			{
				fprintf(f,"%s\t%d\n",ng->name,ng->serial);
			}
		}
	}
	fprintf(f,"#\n");
	fclose(f);

	remove(path1);
	rename(path2,path1);

	/* now edit the Rule file */
	sprintf(path1,"%s.GlobalRule",options.ngroups_data);
	f_in = fopen_werr(path1,"r",NULL);
	if(f_in == NULL)
		return;

	sprintf(path2,"%s.GlobalRul2",options.ngroups_data);
	f = fopen_werr(path2,"w",NULL);

	newsg_copy_out(f_in,f,"$ header only:");

	/* write out newsgroups with header-only downloads */
	for(ix=0; ix<n_ngroups2; ix++)
	{
		if(ng_index[ix]->maillist)
			continue;

		if(ng_index[ix]->ng_flags & NG_HEADFETCH)
		{
			fprintf(f,"%s\t*\t*\t*\t*\txover\n",ng_index[ix]->name);
		}
	}
	fprintf(f,"#\n");

	/* copy the remainder of the Rule file */
	newsg_copy_out(f_in,NULL,"#");
	newsg_copy_out(f_in,f,"");

	fclose(f_in);
	fclose(f);

	remove(path1);
	rename(path2,path1);
}   /* end of newsg_save_newshound2 */



static void newsg_save_newshound()
/********************************/
{
	char *name;
	os_error *error;
	os_regset regs;
	char server[4];
	char buf[64];
	char path[180];

	regs.r[0] = 10;
	regs.r[1] = (int)options.ngroups_data;
	regs.r[2] = (int)buf;
	regs.r[3] = 1;
	regs.r[4] = 0;
	regs.r[5] = sizeof(buf);
	regs.r[6] = 0;

	while(regs.r[3] > 0)
	{
		error = os_swix(0x0c,&regs);           /* OS_GBPB 10, read directory entries */
		if((error != NULL) || (regs.r[3] == 0))
			break;

		name = &buf[20];
		if(strcmp(&name[3],"Group")==0)
		{
			sprintf(path,"%s.%s",options.ngroups_data,name);
			memcpy(server,name,3);
			server[3] = 0;

			newsg_save_newshound2(server);
		}
	}
}   /* end of newsg_save_newshound */




static void newsg_save_termite()
/******************************/
{
	FILE *f;
	int  ix;
	NEWSG *ng;
	char flags[6];
	char path1[180];

	sprintf(path1,"%s.Newsgroups",options.ngroups_data);
	f = fopen_werr(path1,"w",NULL);
	if(f == NULL)
		return;

	for(ix=0; ix<n_ngroups2; ix++)
	{
		ng = ng_index[ix];
		if(ng->maillist)
			continue;


		strcpy(flags,"AWC1N");
		if(ng->active==0)
			flags[0] = 'S';

		if(ng->moderated == 'n')
			flags[1] = 'R';

		fprintf(f,"%s %s %.6d %.6d\n",flags,ng->name,ng->serial,ng->serial2);
	}
	fclose(f);
}   /* end of newsg_save_termite */




void newsg_save(int type)
/*********************/
/* Type=1 only mailing lists have changed, no need to update news transports */
{
	BLIST *b;
	int  parent;

	if(type != 1)
	{
		switch(options.news_transport)
		{
		case X_VOYAGER:
			newsg_save_voyager();
			break;

		case X_ANT:
			newsg_save_ant();
			break;

		case X_NEWSHOUND:
			newsg_save_newshound();
			break;

		case X_TERMITE:
			newsg_save_termite();
			break;

		default:
			break;
		}
	}

	b = &newsglist;
	b->index_ptr = (void **)ng_index;
	b->n_entries = n_ngroups;   /* to save newsgroups and mailing lists */
	blist_save_data(b,"Newsgroups");
	b->n_entries = n_ngroups2;

	if((source_count > 0) || (type == 1))
	{
		source_count = 0;

		set_cats_extent(&src_fr,0);
		parent = category_lookup(&src_fr,"news",0);
		category_sort(&src_fr,parent);
		parent = category_lookup(&src_fr,"mail",0);
		category_sort(&src_fr,parent);
		redraw_cats_lines(&src_fr,0);
		save_catfile(&src_fr,1);
	}
}   /* end of newsg_save */





int newsg_bitmap(int num)
/***********************/
/* num >= 0, clear this bit,
   num = -1  find a free bit and set it */
{
	FILE *f;
	int  i;
	int  c;
	int  ix;
	int  found;
	char buf[256];

	if(options.news_transport != X_VOYAGER)
		return(0);

	sprintf(buf,"%s.Group.Index",options.ngroups_data);

	f = fopen_werr(buf,"r+","");
	if(f == NULL)
		return(0);

	if(num >= 0)
	{
		ix = num;

		for(i=0; i<(num>>3); i++)
		{
			fgetc(f);
		}
		c = fgetc(f);
		c = c & ~(1 << (num & 3));
		fflush(f);
		fseek(f,(long)num >> 3,SEEK_SET);
		fputc(c,f);
	}
	else
	{
		/* find free bit */
		found = 0;
		ix = 0;
		while(!feof(f))
		{
			c = fgetc(f);
			for(i=0; i<8; i++)
			{
				if(((c >> i) & 1) == 0)
				{
					ix += i;
					c |= (i << 1);
					fflush(f);
					fseek(f,(long)ix >> 3,SEEK_SET);
					fputc(c,f);
					found = 1;
					break;
				}
			}
			if(found) break;

			ix += 8;
		}
	}
	fclose(f);
	return(ix);
}   /* end of newsg_bitmap */






void newsg_selected_box(int *hits)
/********************************/
{
	int  user;
	char buf[12];


	switch(dbox_menu_field)
	{
	case 5:
		get_sig_name(hits[0],buf);
		if(buf[0]==0)
			strcpy(buf,string_users);
		dbox_setfield(dbox_newsg,dbox_menu_field,buf);
		break;

	case 6:
		dbox_newsg_box = box_lookup_number(hits[0]);
		dbox_setfield(dbox_newsg,dbox_menu_field,get_box_name(dbox_newsg_box));
		break;

	case 9:
		if(hits[0] == 0)
			user = 0;
		else
			user = mbox_list[hits[0]-1]+1;
		dbox_setfield(dbox_newsg,dbox_menu_field,get_user_id3(user));
		dbox_newsg_default_user = user;

		/* set the signature for this user */
		if(user > 0)
			dbox_setfield(dbox_newsg,5,options.mailbox[user-1].signature);
		else
			dbox_setfield(dbox_newsg,5,"");
		break;
	}
}   /* end of newsg_selected_box */





BOOL dbox_newsg_raw_handler(dbox d, void *event, void *handle)
/*************************************************************/
{
	wimp_eventstr *e;
	wimp_mousestr *mouse;

	e = (wimp_eventstr *)event;

	switch (e->e)
	{
	case wimp_EBUT:
		/* click on icon.  get icon number. */
		mouse = &e->data.but.m;
		switch(dbox_menu_field = mouse->i)
		{
		case 5:
			dbox_menu(sigs_make_menu(0,string_users),newsg_selected_box,mouse);
			return(TRUE);

		case 6:   /* archive to */
			make_boxes_menu(0x200,NULL);
			dbox_menu(wmenu_boxes_names,newsg_selected_box,mouse);
			return(TRUE);

		case 9:   /* default user */
			dbox_menu(make_users_menu(1),newsg_selected_box,mouse);
			return(TRUE);
		}
	}
	return(help_handler(event,HELP_NGEDIT));
}   /* end of dbox_newsg_raw_handler */




void dbox_newsg_handler(dbox d, void *handle)
/*******************************************/
{
	int  group;
	int  i;
	NEWSG *ng = NULL;
	NEWSG *ng2;
	BLIST *b;
	int  new_source;
	int *pi;
	const char *source_type;
	char *p;
	char *name_buf_ptr;
	char name_buf[80];
	char buf[32];

	ng2 = ng_edit;

	group = (int)handle;
	if(group >= 0)
		ng = ng_index[group];

	switch(dbox_get(d))
	{
	case 1:
	case 0:
		/* don't allow change of newsgroup name for an existing newsgroup */
		dbox_getfield(d,2,ng2->name,80);

		if(ng2->name[0] <= ' ')
		{
			beep();    /* name doesn't start with printable character */
			return;
		}

		ng2->ng_flags = 0;

		if(newsg_edit_blist==&newsglist)
		{
			/* Newsgroup */

			ng2->maillist=0;
			if(dbox_getnumeric(d,7))  ng2->ng_flags |= NG_HEADFETCH;
			if(options.news_transport == X_NEWSHOUND)
				dbox_getfield(d,12,ng2->server,sizeof(ng2->server));
			newsg_back_articles = dbox_getnumeric(d,11);
			name_buf_ptr = NULL;
		}
		else
		{
			/* Mailing List */

			strcpy_lc(name_buf,ng2->name);
			if(memcmp(name_buf,"mail.",5) != 0)
			{
				sprintf(ng2->name,"mail.%s",name_buf);
			}
			else
				strcpy(ng2->name,name_buf);

			ng2->maillist = 1;
			if(memcmp(ng2->name,"mail.",5) != 0)
			{
				werr(0,"Maillist address must begin with 'mail.', eg. 'mail.ovationp-l'");
				return;
			}

			dbox_getfield(d,3,name_buf,sizeof(name_buf));   /* name (comment) for mailing list */
			if(name_buf[0]==0)
			{
				/* none, make it from the address */
				strcpy(name_buf,&ng2->name[5]);
				if((p = strchr(name_buf,'@'))!=NULL)
					*p = 0;
			}

			name_buf_ptr = name_buf;

			ng2->strip_n_chars = dbox_getnumeric(d,8);
		}

		ng2->default_user = dbox_newsg_default_user;
		ng2->box = dbox_newsg_box;

		if(dbox_getnumeric(d,13)) ng2->ng_flags |= NG_SUBJECT_TAGS;
		if(dbox_getnumeric(d,14)) ng2->ng_flags |= NG_READ_ONLY;
		if(dbox_getnumeric(d,15)) ng2->ng_flags |= NG_DIGESTS;

		i = dbox_getnumeric(d,4);
		if(i > 255)
		{
			werr(0,"Maximum expiry period is 255 days");
			i = 255;
		}
		ng2->expiry = i;

		dbox_getfield(d,5,ng2->signature,11);
		if(memcmp(ng2->signature,"(user's",7)==0)
			ng2->signature[0] = 0;

		ng2->sign_messages = dbox_getnumeric(d,10);


		if(strchr(ng2->name,'.')==NULL)
		{
			if(query(err_newsgroups_no_dot,NULL)==0)
				return;
		}

		if((ng2->ng_flags & NG_HEADFETCH) && ((transport_opts & TOPS_NEWS_FETCH) == 0))
		{
			werr(0,"Header only downloads are not supported by this transport");
			return;
		}

		dbox_getfield(d,6,buf,sizeof(buf));
		ng2->box = get_box_number(buf);

		if(group < 0)
		{
			/* new newsgroup  */
			if(newsg_lookup(ng2->name) != NULL)
			{
				werr(0,"Newsgroup '%s' already exists",ng2->name);
				return;
			}

			if(options.news_transport == X_VOYAGER)
			{
				ng2->serial = -1;
				pi = (int *)ng2->server;
				*pi = 0;
			}
			else if(options.news_transport == X_NEWSHOUND)
			{
				ng2->serial = -1;
				if(ng2->server[0]==0)
				{
					strcpy(ng2->server,options.newshound_mnem);  /* default server */
				}
			}
			else
				ng2->serial = 0;


			ng2->source = category_lookup(&src_fr,ng2->name,0);
			if(ng2->source == 0)
			{
				/* add this newsgroup to the list of source names */
				if(ng2->maillist)
					source_type = "mail";
				else
					source_type = "news";
				source_count += category_add_child(&src_fr,ng2->name,source_type,&new_source,0);
				ng2->source = new_source;
			}
		}

		if(ng2->source > 0)
		{
			category_change_name(&src_fr,ng2->source,ng2->name,name_buf_ptr);
		}

		newsg_back_articles_ng = ng2;
		ng2->serial = -newsg_back_articles;


		if(group < 0)
		{
			ng2->active = 1;
			ng2->moderated = 'y';
			ng2->serial2 = 0;

			ng2->ng_num = newsg_bitmap(-1);      /* find and set newsgroup bit map */

			ng_index[n_ngroups] = ng2;
			n_ngroups++;
			if(ng2->maillist == 0)
				n_ngroups2++;
		}

		ng2->length = (sizeof(NEWSG) + strlen(ng2->name) + 3) & ~3;
		if((ng != NULL) && (ng->length >= ng2->length))
		{
			/* editing an existing newsgroup, data is no longer than previous length */
			memcpy(ng,ng2,ng2->length);
			newsg_back_articles_ng = ng;
			free(ng2);
		}
		else
		{
			ng_index[group] = ng2;
		}
		ng_edit = NULL;

		newsg_sort();


		if(ng2->maillist)
			b = &mlistlist;
		else
			b = &newsglist;
		blist_set_extent(b,7);
		redraw_blist(b);

		newsg_save(ng2->maillist);
		newsg_back_articles_ng = NULL;
		break;

	default:
		break;
	}

	if(ng_edit != NULL)
		free(ng_edit);
	dbox_dispose(&dbox_newsg);
	dbox_newsg = NULL;
}   /* end of dbox_newsg_handler */





void newsg_edit(BLIST *b, int group, char *new_name)
/**************************************************/
{
	int  box;
	int  back_articles=0;

	check_newsg_length();
	if(dbox_newsg != NULL)
	{
		if(newsg_edit_blist != b)
		{
			/* change to a different type (mlist / newsg) */
			dbox_dispose(&dbox_newsg);
			dbox_newsg = NULL;
		}

		free(ng_edit);  /* and then re-allocate */
	}

	ng_edit = (NEWSG *)calloc(1,sizeof(NEWSG)+100);
	newsg_edit_blist = b;
	if(b==&newsglist)
	{
		if(dbox_newsg == NULL)
			dbox_newsg = dbox_new("NGEdit");
		box = options.news_box;
	}
	else
	{
		if(dbox_newsg == NULL)
			dbox_newsg = dbox_new("MLEdit");
		box = options.mlist_box;
	}
	dbox_setfield(dbox_newsg,6,get_box_name(box));


	if(group >= 0)
	{
		memcpy(ng_edit,ng_index[group],ng_index[group]->length);


		if(newsg_edit_blist==&newsglist)
		{
			wimp_set_icon_state(dbox_syshandle(dbox_newsg),2,0,0xf000);
			dbox_setfield(dbox_newsg,2,ng_edit->name);
			dbox_setnumeric(dbox_newsg,7,ng_edit->ng_flags & NG_HEADFETCH);
			if(options.news_transport == X_NEWSHOUND)
				dbox_setfield(dbox_newsg,12,ng_edit->server);
		}
		else
		{
			dbox_setfield(dbox_newsg,2,&ng_edit->name[5]);   /* omit  mail.  */
			dbox_setfield(dbox_newsg,3,expand_source(ng_edit->source,3));
			dbox_setnumeric(dbox_newsg,8,ng_edit->strip_n_chars);
		}

		dbox_setnumeric(dbox_newsg,13,ng_edit->ng_flags & NG_SUBJECT_TAGS);
		dbox_setnumeric(dbox_newsg,14,ng_edit->ng_flags & NG_READ_ONLY);
		dbox_setnumeric(dbox_newsg,15,ng_edit->ng_flags & NG_DIGESTS);
		dbox_setnumeric(dbox_newsg,4,ng_edit->expiry);
		dbox_setfield(dbox_newsg,6,get_box_name(ng_edit->box));

		if(ng_edit->signature[0] == 0)
			dbox_setfield(dbox_newsg,5,string_users);
		else
			dbox_setfield(dbox_newsg,5,ng_edit->signature);


		dbox_setnumeric(dbox_newsg,10,ng_edit->sign_messages);

		dbox_setfield(dbox_newsg,9,get_user_id3(ng_edit->default_user));

	}
	else
	{
		if(newsg_edit_blist==&newsglist)
		{
			if(options.news_transport == X_NEWSHOUND)
				dbox_setfield(dbox_newsg,12,options.newshound_mnem);
		}

		back_articles = 50;
	}

	if(newsg_edit_blist==&newsglist)
	{
		if(options.news_transport == X_NEWSHOUND)
			dbox_setnumeric(dbox_newsg,11,back_articles);
		else
		{
			dbox_fadefield(dbox_newsg,11);
			dbox_fadefield(dbox_newsg,12);
		}
	}

	if(new_name != NULL)
	{
		dbox_setfield(dbox_newsg,2,new_name);
	}

	dbox_raw_eventhandler(dbox_newsg,dbox_newsg_raw_handler,(void *)group);
	dbox_eventhandler(dbox_newsg, dbox_newsg_handler, (void *)group);

	dbox_newsg_default_user = ng_edit->default_user;
	dbox_newsg_box = ng_edit->box;
	dbox_showstatic(dbox_newsg);
}   /* end of newsg_edit */




void newsg_select_all(BLIST *blist, int select, int redraw)
/*********************************************************/
/* select or unselect all newsgroups */
{
	int  i;
	int start;
	int  end;

	if(blist == &newsglist)
	{
		start = 0;
		end = n_ngroups2;
	}
	else
	{
		start = n_ngroups2;
		end = n_ngroups;
	}

	for(i=start; i<end; i++)
	{
		if((ng_index[i] != NULL) && (ng_index[i]->selected != select))
		{
			ng_index[i]->selected = select;
			if(redraw)
			{
				redraw_blist_line(blist,i-start);
			}
		}
	}
	if(redraw==0)
		redraw_blist(blist);
}   /* end of newsg_select_all */




void newsg_delete2(int ix)
/************************/
{
	int  j;

	/* clear newsgroup number bit in bitmap */
	newsg_bitmap(ng_index[ix]->ng_num);

	/* NOTE: don't free() the entry, it might not have been malloc'd */

	for(j=ix+1; j<n_ngroups; j++)
	{
		ng_index[j-1] = ng_index[j];
	}
	newsglist.n_entries--;

	n_ngroups--;
	if(ix < n_ngroups2)
		n_ngroups2--;
}   /* end of newsg_delete2 */



void newsg_delete(BLIST *blist)
/*****************************/
{
	int  i;
	int  start;
	int  end;

	if(blist == &newsglist)
	{
		start = 0;
		end = n_ngroups2;
	}
	else
	{
		start= n_ngroups2;
		end = n_ngroups;
	}

	for(i=0; i<n_ngroups; i++)
	{
		if(ng_index[i]->selected)
		{
			newsg_delete2(i);
			i--;
		}
	}

	newsglist.n_entries = n_ngroups2;
	mlistlist.n_entries = n_ngroups - n_ngroups2;

	if(blist == &newsglist)
		newsg_save(0);
	else
		newsg_save(1);
	blist_set_extent(blist,7);
}   /* end of newsg_delete */



void newsg_set_flag(BLIST *b, int field, int value)
/*************************************************/
/* Newsgroups only, not mailing lists */
{
	int  i;

	for(i=0; i<n_ngroups2; i++)
	{
		if(ng_index[i]->selected)
		{
			switch(field)
			{
			case 1:
				ng_index[i]->active = value;
				break;

			case 2:
				if(value)
					ng_index[i]->ng_flags |= NG_HEADFETCH;
				else
					ng_index[i]->ng_flags &= ~NG_HEADFETCH;
				break;
			}
		}
	}
	newsg_save(0);
	blist_set_extent(b,7);
}   /* end of newsg_set_flag */






void newsg_click_buttons(BLIST *b, wimp_eventdata *d)
/***************************************************/
/* Click on the mail box-list button bar */
{
	int  i;
	int  icon;
	int  click;
	int  user;
	char *sig = NULL;
	int  start, end;
	int  write_maillist;
	char *p;
	char buf[300];    /* same size as Newsgroups field in Write News window */

	icon = d->but.m.i;
	click = d->but.m.bbits;

	if(b == &newsglist)
	{
		start = 0;
		end = newsglist.n_entries;
	}
	else
	{
		start = newsglist.n_entries;
		end = start + mlistlist.n_entries;
	}

	redraw_blist(b);

	switch(icon)
	{
	case 5:    /* add new newsgroup */
		newsg_edit(b,-1,NULL);
		break;

	case 1:    /* delete selected newsgroup */
		newsg_delete(b);
		break;

	case 2:    /* subscribe */
		newsg_set_flag(b,1,1);
		break;

	case 3:    /* unsubscribe */
		newsg_set_flag(b,1,0);
		break;

	case 4:   /* write article */
		user=0;
		write_maillist=0;
		strcpy(buf,"");
		for(i=start; i<end; i++)
		{
			if(ng_index[i]->selected)
			{
				if(ng_index[i]->maillist)
				{
					write_maillist = 1;
					p = ng_index[i]->name;
					new_reply(NULL,&p[5],NULL,NULL,ng_index[i]->default_user,ng_index[i]->signature);
					break;
				}

				if((strlen(buf) + strlen(ng_index[i]->name)) >= (sizeof(buf)-2))
				{
					werr(0,"Too many newsgroups");
					break;
				}

				if(buf[0]!=0)
					strcat(buf,",");
				strcat(buf,ng_index[i]->name);
				if(ng_index[i]->default_user > 0)
					user = ng_index[i]->default_user;

				if(ng_index[i]->signature[0] > ' ')
					sig = ng_index[i]->signature;
			}
		}

		if(write_maillist==0)
			new_reply(NULL,NULL,buf,NULL,user,sig);
		break;
	}

}   /* end of newsg_click_buttons */





void newsg_click_window(BLIST *b,int linenum,int bbits)
/*****************************************************/
{
	int  offset;

	if(b == &newsglist)
		offset = 0;
	else
		offset = n_ngroups2;

	switch(bbits)
	{
	case wimp_BCLICKLEFT:
		newsg_select_all(b,0,1);
		ng_index[linenum+offset]->selected = 1;
		redraw_blist_line(b,linenum);
		break;

	case wimp_BCLICKRIGHT:
		ng_index[linenum+offset]->selected ^= 1;
		redraw_blist_line(b,linenum);
		break;

	case wimp_BLEFT:
	case wimp_BRIGHT:        /* adjust, 2nd click */
		newsg_select_all(b,0,1);
		newsg_edit(b,linenum+offset,NULL);
		break;
	}
}   /* end of newsg_click_window */




void newsg_key_window(BLIST *b,wimp_eventdata *d)
/***********************************************/
{
	int  c;

	switch(c = d->key.chcode)
	{
	case 1:    /* CTRL-A */
		newsg_select_all(b,1,0);
		break;

	case 26:   /* CTRL-Z */
		newsg_select_all(b,0,0);
		break;

	default:
		wimp_processkey(c);
		break;
	}
}   /* end of newsg_key_window */





static void newsg_load_ant(int control)
/*************************************/
{
	FILE *f_in;
	int  ix;
	int  serial;
	int  serial2;
	int  moderated;
	int  headfetch;
	int  expiry;
	int  nofetch;
	int  count;
	NEWSG *ng;
	char *p;
	char buf[120];
	char path1[180];
	char name[80];
	char x[5][16];

	sprintf(path1,"%s./active",options.ngroups_data);
	f_in = fopen(path1,"r");
	if(f_in == NULL)
	{
		werr(0,err_newsgroups_file,path1);
		return;
	}

	while(!feof(f_in))
	{
		if(fgets(buf,sizeof(buf),f_in)==NULL)
			break;
		if(buf[0] == '#')
			continue;

		count = sscanf(buf,"%s %d %d %c %s %s %s %s %s",name,&serial,&serial2,&moderated,x[0],x[1],x[2],x[3],x[4]);

		headfetch = 0;
		nofetch = 0;
		expiry = 0;

		for(ix=0; ix<(count-4); ix++)
		{
			p = x[ix];
			if(strcmp(p,"HEADFETCH")==0)
				headfetch=NG_HEADFETCH;
			else if(strcmp(p,"NOFETCH")==0)
				nofetch=1;
			else if(memcmp(p,"TIME=",5)==0)
				expiry = atoi(&p[5]);
		}

		ng = newsg_lookup(name);
		if(ng == NULL)
		{
			/* need to allocate a new newsgroup */
			ng = newsg_alloc(name);
			if(ng == NULL)
				continue;
		}
		ng->serial = serial;
		ng->serial2 = serial2;
		ng->moderated = moderated;
		ng->ng_flags = (ng->ng_flags & ~NG_HEADFETCH) | headfetch;
		ng->active = nofetch ^ 1;
		ng->expiry = expiry;
	}
	fclose(f_in);
}   /* end of newsg_load_ant */




static void newsg_load_newshound2(char *path, char *server)
/*********************************************************/
{
	FILE *f_in;
	int  serial;
	NEWSG *ng;
	char buf[120];
	char name[80];

	f_in = fopen(path,"r");
	if(f_in == NULL)
	{
		werr(0,err_newsgroups_file,path);
		return;
	}

	newsg_copy_out(f_in,NULL,"# Newsgroups:");

	while(!feof(f_in))
	{
		if(fgets(buf,sizeof(buf),f_in)==NULL)
			break;

		serial = -1;
		sscanf(buf,"%s %d",name,&serial);

		ng = newsg_lookup(name);
		if(ng == NULL)
		{
			/* need to allocate a new newsgroup */
			ng = newsg_alloc(name);
			if(ng == NULL)
				continue;
		}

		if(serial > 0)
			ng->serial = serial;
		ng->active = 1;

		if(!isalpha(ng->server[0]) || !isalpha(ng->server[1]) || !isalpha(ng->server[2]))
			strcpy(ng->server,server);
		else
		{
			if(strcmp_lc(ng->server,server) != 0)
			{
				/* newsgroup in listed on more than one server */
				strcpy(ng->server,"ALL");
			}
		}
	}
	fclose(f_in);
}   /* end of newsg_load_newshound2 */




static void newsg_load_newshound(int control)
/*******************************************/
/* Read each xxxGroup file */
{
	char *name;
	os_error *error;
	os_regset regs;
	char server[4];
	char buf[64];
	char path[180];

	regs.r[0] = 10;
	regs.r[1] = (int)options.ngroups_data;
	regs.r[2] = (int)buf;
	regs.r[3] = 1;
	regs.r[4] = 0;
	regs.r[5] = sizeof(buf);
	regs.r[6] = 0;

	while(regs.r[3] > 0)
	{
		error = os_swix(0x0c,&regs);           /* OS_GBPB 10, read directory entries */
		if((error != NULL) || (regs.r[3] == 0))
			break;

		name = &buf[20];
		if(strcmp(&name[3],"Group")==0)
		{
			sprintf(path,"%s.%s",options.ngroups_data,name);
			memcpy(server,name,3);
			server[3] = 0;

			newsg_load_newshound2(path,server);
		}
	}
}   /* end of newsg_load_newshound */





static void newsg_load_termite(int control)
/*****************************************/
{
	FILE *f_in;
	int  serial;
	int  serial2;
	NEWSG *ng;
	char buf[120];
	char path1[180];
	char flags[12];
	char name[80];

	sprintf(path1,"%s.Newsgroups",options.ngroups_data);
	f_in = fopen(path1,"r");
	if(f_in == NULL)
	{
		werr(0,err_newsgroups_file,path1);
		return;
	}

	while(!feof(f_in))
	{
		if(fgets(buf,sizeof(buf),f_in)==NULL)
			break;
		sscanf(buf,"%s %s %d %d",flags,name,&serial,&serial2);

		ng = newsg_lookup(name);
		if(ng == NULL)
		{
			/* need to allocate a new newsgroup */
			ng = newsg_alloc(name);
			if(ng == NULL)
				continue;
		}
		ng->serial = serial;
		ng->serial2 = serial2;
		ng->active = 1;
		if(flags[0] == 'S')
			ng->active = 0;
		ng->moderated = 'y';
		if(flags[1] == 'R')
			ng->moderated = 'n';
	}
	fclose(f_in);
}   /* end of newsg_load_termite */




static void blist_load_data(BLIST *b,char *fname)
/***********************************************/
/* Load  NewsGroups list */
{
	FILE *f;
	int  length;
	int  file_length;
	char *p;
	int  ix;
	char buf[160];

	sprintf(buf,"%s.%s",path_choices,fname);
	f = fopen(buf,"r");

	b->n_entries = 0;
	b->max_entries = 0;

	if(f!=NULL)
	{
		if(b->data_ptr != NULL)
			free(b->data_ptr);

		file_length = get_filelength(buf);
		if((b->data_ptr = malloc(file_length)) == NULL)
		{
			malloc_err(78);
			fclose(f);
			return;
		}

		if(file_length > 4)
		{
			fread(b->data_ptr,1,file_length,f);
			b->n_entries = *(int *)(b->data_ptr);
		}
		fclose(f);
	}

	b->max_entries = b->n_entries + 50;

	b->index_ptr = malloc(b->max_entries * sizeof(void *));
	if(b->index_ptr == NULL)
	{
		malloc_err(79);
		return;
	}

	p = b->data_ptr + 4;

	for(ix=0; ix<b->n_entries; ix++)
	{
		if(p >= &(b->data_ptr)[file_length])
		{
			werr(0,"%s file may be corrupt",fname);
			break;
		}
		length = p[0];    /* first byte gives the length of the entry */
		b->index_ptr[ix] = (void *)p;

		p += length;
	}
}   /* end of blist_load_data */




void newsg_load(int control)
/***********************/
/* Control =1  keep article serial numbers NOT USED */
{
	BLIST *b;
	int  news_source;

	b = &newsglist;

	blist_load_data(b,"Newsgroups");
	n_ngroups = b->n_entries;
	n_ngroups_max = b->max_entries;
	ng_index = (NEWSG **)b->index_ptr;
	source_count = 0;

	newsg_select_all(&newsglist,0,0);
	newsg_select_all(&mlistlist,0,0);

	switch(options.news_transport)
	{
	case X_VOYAGER:
		newsg_load_voyager(control);
		break;

	case X_ANT:
		newsg_load_ant(control);
		break;

	case X_NEWSHOUND:
		newsg_load_newshound(control);
		break;

	case X_TERMITE:
		newsg_load_termite(control);
		break;
	}
	b->n_entries = n_ngroups;
	b->max_entries = n_ngroups_max;

	if(source_count > 0)
	{
		news_source = category_lookup(&src_fr,"News",0);
		category_sort(&src_fr,news_source);
	}
	newsg_sort();
}  /* end of newsg_load */



static char *menustr_newsg = "Add,Edit,Activate,Deactivate,Header only,Full body,Select all ^A,Delete ^X,Clear ^Z";

static menu menu_newsg;




void newsg_select(BLIST *b, int line, int selected)
/********************************************/
{
	int  start=0;

	if(b->type == BLIST_MLIST)
	{
		start = n_ngroups2;
	}

	if(selected == 2)
		ng_index[line+start]->selected ^= 1;
	else
		ng_index[line+start]->selected = selected;

	redraw_blist_line(b,line);
}   /* end of newsg_select */




void newsg_menu_proc(void *handle, char *hits)
/********************************************/
{
	int  i;
	BLIST *b;
	int  start;
	int  end;

	b = (BLIST *)handle;

	if(b == &newsglist)
	{
		start = 0;
		end = n_ngroups2;
	}
	else
	{
		start = n_ngroups2;
		end = n_ngroups;
	}

	switch(hits[0])
	{
	case 1:   /* Add */
		newsg_edit(b,-1,NULL);
		break;

	case 2:   /* Edit */
		for(i=start; i<end; i++)
		{
			if(ng_index[i]->selected)
			{
				newsg_edit(b,i,NULL);
				break;
			}
		}
		break;

	case 3:   /* Subscribe */
		newsg_set_flag(b,1,1);
		break;

	case 4:   /* Unsubscribe */
		newsg_set_flag(b,1,0);
		break;

	case 5:   /* header only */
		newsg_set_flag(b,2,1);
		break;

	case 6:   /* full body */
		newsg_set_flag(b,2,0);
		break;

	case 7:  /* select all */
		newsg_select_all(b,1,0);
		return;

	case 8:
		newsg_delete(b);
		break;

	case 9:
		newsg_select_all(b,0,0);
		break;
	}

	if(blist_current_menu == menu_newsg)
	{
		newsg_select(b,blist_current_menu_line,0);
	}
}   /* end of newsg_menu_proc */



menu newsg_menu_maker(void *handle)
/*********************************/
{
	int  ix;
	int  count;
	BLIST *b;
	int  start;
	int  end;
	int  fade;
	int  blist_num;
	static char fades[11] =    {0,0,1,1,1,1,1,0,1,0,0};  /* fade these if no selection */
	static char ml_fades[11] = {0,0,0,1,1,1,1,0,0,0,0};  /* fade these if mailing list */

	b = (BLIST *)handle;
	if(b == &newsglist)
	{
		start = 0;
		end = n_ngroups2;
		blist_num = BLIST_NEWSG;
	}
	else
	{
		start = n_ngroups2;
		end = n_ngroups;
		blist_num = BLIST_MLIST;
	}

	/* are there any selected items in this list */
	count=0;

	for(ix=start; ix<end; ix++)
	{
		if(ng_index[ix]->selected)
		{
			count++;
		}
	}

	blist_current_menu = NULL;
	if(count == 0)
	{
		/* no items selected, menu button selects one */
		/* get line number of last muse click */
		if((blist_current_menu_line = list_get_linenum(b->w_list)) < b->n_entries)
		{
			ng_index[blist_current_menu_line+start]->selected = 1;
			redraw_blist_line(b,blist_current_menu_line);

			blist_current_menu = menu_newsg;
			blist_current_menu_blist = blist_num;
			count = 1;
		}
	}

	/* fade menu items if there is no selection */
	for(ix=1; ix<9; ix++)
	{
		fade = 0;
		if(fades[ix])
		{
			if((b == &mlistlist) && (ml_fades[ix]))
			{
				fade = 1;
			}
			else if(count == 0)
				fade = 1;
			else
				fade = 0;
			menu_setflags(menu_newsg,ix,0,fade);
		}
	}

	if(count != 1)
		menu_setflags(menu_newsg,2,0,1);    /* fade Edit option */


	return(menu_newsg);
}   /* end of newsg_menu_maker */





void newsg_check_sources()
/************************/
/* Check that Source numbers in the newsgroups list agree with the sources list */
{
	int  ix;
	int  source;
	int  count=0;
	const char *source_type;
	NEWSG *ng;

	for(ix=0; ix<n_ngroups; ix++)
	{
		ng = ng_index[ix];

		source = category_lookup(&src_fr,ng->name,0);
		if(source == 0)
		{
			/* allocate a source for this newsgroup */
			if(ng->maillist)
				source_type = "mail";
			else
				source_type = "news";

			count += category_add_child(&src_fr,ng->name,source_type,&source,0);
		}

		if(source != ng->source)
		{
			count++;
			ng->source = source;
		}
	}

	if(count > 0)
	{
		newsg_save(1);
		save_catfile(&src_fr,1);
	}
}  /* end of newsg_check_sources */




char *newsg_lookup_source(int source)
/***********************************/
/* Is this Source being used in the newsgroups list */
{
	int  ix;

	for(ix=0; ix<n_ngroups; ix++)
	{
		if(source == ng_index[ix]->source)
			return(ng_index[ix]->name);
	}
	return(NULL);
}   /* newsg_lookup_source */






int newsg_make_list(char *fname)
/******************************/
{
	FILE *f;
	NEWSG *ng;
	int  ix;

	f = fopen_werr(fname,"w",NULL);
	if(f==NULL)
		return(-1);

	/* newsgroups only, not mailing lists */
	for(ix=0; ix<n_ngroups2; ix++)
	{
		ng = ng_index[ix];
		if(ng->maillist==0)
		{
			fprintf(f,"%s %d %d\n",ng->name,ng->active,ng->expiry);
		}
	}
	fclose(f);
	return(0);
}   /* end of newsg_make_list */




void newsg_wimp_message(wimp_eventdata *d)
/****************************************/
/*  Word 0:  Active
         1:  Header only
         2:  Expiry
         3:  spare
         4:  spare
         5:  spare
         6:  newsgroup name
*/
{
	int  ix;
	int  response;
	wimp_msgstr *m;
	char *name;
	NEWSG *ng;
	char fname[80];

	m = &d->msg;
	name = &m->data.chars[24];
	ix = newsg_lookup_ix(name);
	if(ix >= 0)
		ng = ng_index[ix];
	response = -1;

	switch(m->data.words[0])
	{
	case 1:   /* list newsgroups */
		m->hdr.your_ref = m->hdr.my_ref;

		sprintf(fname,"%stmp.newsg_list",pluto_path);
		strcpy(m->data.chars,fname);
		if(newsg_make_list(fname)==0)
		{
			wimp_sendmessage(wimp_EACK,m,0);
			response = 0;
		}
		break;

	case 2:   /* read newsgroup */
		if(ix >= 0)
		{
			m->data.words[0] = ng->active;
			m->data.words[1] = ng->ng_flags & 1;
			m->data.words[2] = ng->expiry;
			m->data.words[3] = 0;
			m->data.words[4] = 0;
			m->data.words[5] = 0;
			strcpy(name,ng->name);

			response = 0;
		}
		break;

	case 3:   /* change newsgroup */
		if(ix >= 0)
		{
			ng->active = m->data.words[0];
			ng->ng_flags = (ng->ng_flags & ~NG_HEADFETCH) | m->data.words[1];

			if(m->data.words[2] >= 0)
				ng->expiry = m->data.words[2];

			response = 0;
		}
		break;

	case 4:   /* add newsgroup */
		if(ix >= 0)
		{
			newsg_edit(&newsglist,ix,NULL);
		}
		else
		{
			newsg_edit(&newsglist,-1,m->data.chars);
		}
		break;

	case 5:   /* remove newsgroup */
		if(ix >= 0)
		{
			newsg_delete2(ix);
			response = 0;
		}
		break;
	}
}   /* end of newsg_wimp_message */





void init_newsg()
/***************/
{
	menu_newsg = menu_new("Newsgroups",menustr_newsg);

	/* window for newsgroups list */
	blist_register(&newsglist,BLIST_NEWSG,"NGBar");
	event_attachmenumaker(newsglist.w_list,newsg_menu_maker,newsg_menu_proc,(void *)(&newsglist));

	/* window for mailing lists list */
	blist_register(&mlistlist,BLIST_MLIST,"MLBar");
	event_attachmenumaker(mlistlist.w_list,newsg_menu_maker,newsg_menu_proc,(void *)(&mlistlist));

	newsg_load(0);
	newsg_check_sources();
}   /* end of init_newsg */



