/*
    NewsCoaster
    Copyright (C) 1999-2002 Mark Harman

    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 2 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 to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

    NewsCoaster Homepage :
        http://newscoaster.tripod.com/

    Mailing List to hear about announcements of new releases etc at:
        http://groups.yahoo.com/group/newscoaster-announce/
*/

// labels:
// Label1 for checks (std frames)
// Label2 for strings (dbl high frames)
// Label; for other noframe objects

#include "mui_headers.h"
#include <mui/NFloattext_mcc.h>
#include <mui/NListview_mcc.h>
#include <mui/TextEditor_mcc.h>
#include <mui/betterstring_mcc.h>
#include <mui/NListtree_mcc.h>
#include <mui/Toolbar_mcc.h>

#include <exec/exec.h>
#include <proto/socket.h>
#include <netdb.h>
#include <proto/rexxsyslib.h>
#include <proto/locale.h>

#include <time.h>
#include <string.h>
#include <ctype.h>

#include "Vector.h"
#include "various.h"
#include "ViewWindow.h"
#include "WriteWindow.h"
#include "main.h"
#include "Indices.h"
#include "misc.h"
#include "StatusWindow.h"
#include "netstuff.h"
#include "general.h"
#include "regist.h"
#include "ChoiceList.h"
#include "DateHandler.h"
#include "strings.h"
#include "lists.h"

#define __USE_SYSBASE

static struct StackSwapStruct *g_sss;
static struct ExecBase *g_SysBase;

#define SysBase g_SysBase

#define TextList(ftxt)	NListviewObject, MUIA_Weight, 50, MUIA_NList_Input, FALSE, MUIA_NListview_NList, NFloattextObject, MUIA_Frame, MUIV_Frame_ReadList, MUIA_Background, MUII_ReadListBack, MUIA_NFloattext_Text, ftxt, MUIA_NFloattext_TabSize, 4, MUIA_NFloattext_Justify, TRUE, End, End

struct Library *MUIMasterBase;

//char line_buffer_g[MAXLINE + 1] = "";
char status_buffer_g[1025] = "";
//char filename_g[1025] = "";
//char filenamenew_g[1025] = "";

static char scrtitle[256]="";
static char base_scrtitle[256]="";

const float ver=1.54;
char version[]="1.54";
char newscoaster_name[256] ="";
char muiappversion[256] ="";
User * currentUser = NULL;

static char messagelistformat[64] = "";

BOOL DEBUG=FALSE;

int topenum=1000;

/* Menu for the Main Window
 */
static struct NewMenu MenuData1[]= {
	{NM_TITLE,"Project",						0,0,0,	(APTR)MEN_PROJECT},
	{NM_ITEM,"Fetch News",					0,0,0,	(APTR)MEN_GETNEWS},
	{NM_ITEM,"Fetch News for this Group",0,0,0,	(APTR)MEN_GETNEWSSINGLE},
	{NM_ITEM,"Send News",					0,0,0,	(APTR)MEN_SENDNEWS},
	{NM_ITEM,"Fetch Group List",			0,0,0,	(APTR)MEN_GETGROUPSDEF},
	{NM_ITEM,"Fetch New Groups",			0,0,0,	(APTR)MEN_GETNEWGROUPSDEF},
	{NM_ITEM,"Disconnect From Newsserver",0,NM_ITEMDISABLED,0,	(APTR)MEN_DISCONNECT},
	{NM_ITEM,NM_BARLABEL,					0,0,0,	(APTR)0},
	{NM_ITEM,"User Info...",				0,0,0,	(APTR)MEN_USER},
	{NM_ITEM,"About NewsCoaster...",		"?",0,0,	(APTR)MEN_ABOUT},
	{NM_ITEM,"About MUI...",				0,0,0,	(APTR)MEN_ABOUTMUI},
	{NM_ITEM,"System Information...",	0,0,0,	(APTR)MEN_SYSINFO},
	{NM_ITEM,"Iconify",						"H",0,0,	(APTR)MEN_ICONIFY},
	{NM_ITEM,"Quit",							"Q",0,0,	(APTR)MEN_QUIT},
	
	{NM_TITLE,"Newsgroups",					0,0,0,	(APTR)MEN_NEWSGROUPS},
	{NM_ITEM,"New Newsgroup...",			"N",0,0,	(APTR)MEN_NEWNEWSGROUP},
	{NM_ITEM,"Edit Newsgroup...",			0,0,0,	(APTR)MEN_EDITNG},
	{NM_ITEM,"Advanced Settings...",		0,0,0,	(APTR)MEN_NGADV},
	{NM_ITEM,"Delete Newsgroup",			0,0,0,	(APTR)MEN_DELNG},
	{NM_ITEM,"Archive Newsgroup...",		0,0,0,	(APTR)MEN_ARCHIVENG},
	{NM_ITEM,"Groups Manager...",			0,0,0,	(APTR)MEN_GROUPMANDEF},
	{NM_ITEM,"View",							0,0,0,	(APTR)MEN_VIEWGROUPS},
	{NM_SUB,"List",							0,CHECKIT|CHECKED,0,(APTR)MEN_VIEWGROUPSLIST},
	{NM_SUB,"Tree",							0,CHECKIT,0,	(APTR)MEN_VIEWGROUPSTREE},
	{NM_ITEM,NM_BARLABEL,					0,0,0,	(APTR)0},
	{NM_ITEM,"Sort Groups",					0,0,0,	(APTR)MEN_SORT},
	{NM_ITEM,"Search Groups...",			0,0,0,	(APTR)MEN_SEARCH},
	{NM_ITEM,"Group Statistics...",		0,0,0,	(APTR)MEN_STATS},
	{NM_ITEM,NM_BARLABEL,					0,0,0,	(APTR)0},
	{NM_ITEM,"Reset Group Article Pointer ",0,0,0,	(APTR)MEN_RESETGROUPPTR},
	{NM_ITEM,"Reset All Groups' Pointers ",0,0,0,	(APTR)MEN_RESETALLPTR},
	{NM_ITEM,NM_BARLABEL,					0,0,0,	(APTR)0},
	{NM_ITEM,"Update Groups",				0,0,0,	(APTR)MEN_UPDATEGROUPS},
	{NM_ITEM,"Update Index",				0,0,0,	(APTR)MEN_UPDATEINDEX},
	{NM_ITEM,"Update All Indices",		0,0,0,	(APTR)MEN_UPDATEALLIND},
	{NM_ITEM,"Import Messages...",		0,0,0,	(APTR)MEN_IMPORT},
	{NM_TITLE,"Messages",					0,0,0,	(APTR)MEN_MESSAGES},
	{NM_ITEM,"View",							0,0,0,	(APTR)MEN_VIEWMESSAGES},
	{NM_SUB,"Flat",							0,CHECKIT|CHECKED,0,(APTR)MEN_VIEWMESSAGESLIST},
	{NM_SUB,"Threaded",						0,CHECKIT,0,	(APTR)MEN_VIEWMESSAGESTREE},
	{NM_ITEM,"Read Message",				0,0,0,	(APTR)MEN_READ},
	{NM_ITEM,"Edit Message...",			0,0,0,	(APTR)MEN_EDIT},
	{NM_ITEM,"Supersede Message...",		0,0,0,	(APTR)MEN_SUPER},
	{NM_ITEM,"Cancel Message",				0,0,0,	(APTR)MEN_CANCEL},
	{NM_ITEM,"Delete Message",				"D",0,0,	(APTR)MEN_DELMESS},
	{NM_ITEM,"Undelete Message",			0,0,0,	(APTR)MEN_UNDELMESS},
	{NM_ITEM,"Export Message",				"E",0,0,	(APTR)MEN_EXP},
	{NM_ITEM,"View Header",				   0,0,0,	(APTR)MEN_VIEWHEADER},
	{NM_ITEM,"Move Message...",			"M",0,0,	(APTR)MEN_MOVE},
	{NM_ITEM,"Copy Message...",			"C",0,0,	(APTR)MEN_COPY},
	{NM_ITEM,"Add to Killfile...",		0,0,0,	(APTR)MEN_KILLMESS},
	{NM_ITEM,"Export Address to YAM",	0,0,0,	(APTR)MEN_YAMADDRESS},
	{NM_ITEM,NM_BARLABEL,					0,0,0,	(APTR)0},
	{NM_ITEM,"Post New Message",			"P",0,0,	(APTR)MEN_POST},
	{NM_ITEM,"Followup Message...",		"F",0,0,	(APTR)MEN_FOLLOWUP},
	{NM_ITEM,"Reply via Email...",		"R",0,0,	(APTR)MEN_REPLY},
	{NM_ITEM,"Followup and Reply...",	"B",0,0,	(APTR)MEN_BOTH},
	{NM_ITEM,NM_BARLABEL,					0,0,0,	(APTR)0},
	{NM_ITEM,"Permanently Delete",		0,0,0,	(APTR)MEN_PD},
	{NM_SUB,"Selected Messages",			".",0,0,	(APTR)MEN_PDTHIS},
	{NM_SUB,"All Read Messages",			0,0,0,	(APTR)MEN_PDREAD},
	{NM_SUB,"All Online Headers",			0,0,0,	(APTR)MEN_PDONLINE},
	{NM_SUB,"All Duplicates",				0,0,0,	(APTR)MEN_PDDUP},
	{NM_SUB,"All in this Group",			"/",0,0,	(APTR)MEN_PDALL},
	{NM_SUB,NM_BARLABEL,						0,0,0,	(APTR)0},
	{NM_SUB,"ALL Messages",					0,0,0,	(APTR)MEN_PDALLALL},
	{NM_ITEM,"Select",						0,0,0,	(APTR)MEN_SELECT},
	{NM_SUB,"All",								"A",0,0,	(APTR)MEN_SELECTALL},
	{NM_SUB,"None",							0,0,0,	(APTR)MEN_SELECTNONE},
	{NM_SUB,"Toggle",							0,0,0,	(APTR)MEN_SELECTTOGGLE},
	{NM_SUB,"All from this poster",		0,0,0,	(APTR)MEN_SELECTFROM},
	{NM_SUB,"All with this subject",		0,0,0,	(APTR)MEN_SELECTSUBJECT},
	{NM_SUB,"All Read Messages",			0,0,0,	(APTR)MEN_SELECTREAD},
	{NM_SUB,"All Unread Messages",		0,0,0,	(APTR)MEN_SELECTUNREAD},
	{NM_ITEM,"Mark as",						0,0,0,	(APTR)MEN_MARK},
	{NM_SUB,"Unread",							0,0,0,	(APTR)MEN_MARKUNREAD},
	{NM_SUB,"Read",							0,0,0,	(APTR)MEN_MARKREAD},
	{NM_SUB,"Held",							0,0,0,	(APTR)MEN_MARKHELD},
	{NM_SUB,"Queued",							0,0,0,	(APTR)MEN_MARKQUEUED},
	{NM_SUB,"Normal",							0,0,0,	(APTR)MEN_MARKNORMAL},
	{NM_SUB,"Important",						0,0,0,	(APTR)MEN_MARKIMPORTANT},
	{NM_ITEM,"Change Date To Current",	0,0,0,	(APTR)MEN_CURRENTDATE},
	{NM_ITEM,"Download Body",				0,0,0,	(APTR)MEN_DOWNLOADBODY},
	{NM_ITEM,"Join Messages...",			0,0,0,	(APTR)MEN_JOINMSGS},
	
	{NM_TITLE,"Preferences",				0,0,0,	(APTR)MEN_PREFS},
	{NM_ITEM,"Program Settings...",		0,0,0,	(APTR)MEN_ACCOUNT},
	{NM_ITEM,"KillFile...",					0,0,0,	(APTR)MEN_KILLFILE},
	{NM_ITEM,"Users...",						0,0,0,	(APTR)MEN_USERS},
	{NM_ITEM,"Change Password...",		0,0,0,	(APTR)MEN_CPWD},
	{NM_ITEM,"MUI Settings...",			0,0,0,	(APTR)MEN_MUIPREFS},

	{NM_END,NULL,0,0,0,(APTR)0},
};

Object *menustrip;
Object *menuitem_GETNEWS;
Object *menuitem_GETNEWSSINGLE;
Object *menuitem_SENDNEWS;
Object *menuitem_GETGROUPSDEF;
Object *menuitem_GETNEWGROUPSDEF;
Object *menuitem_DISCONNECT;
Object *menuitem_VIEWGROUPS;
Object *menuitem_VIEWMESSAGES;
Object *menuitem_UPDATEGROUPS;
Object *menuitem_UPDATEINDEX;
Object *menuitem_UPDATEALLIND;
Object *menuitem_IMPORT;
Object *menuitem_READ;
Object *menuitem_EDIT;
Object *menuitem_SUPER;
Object *menuitem_CANCEL;
Object *menuitem_DELMESS;
Object *menuitem_UNDELMESS;
Object *menuitem_EXP;
Object *menuitem_MOVE;
Object *menuitem_COPY;
Object *menuitem_KILLMESS;
Object *menuitem_YAMADDRESS;
Object *menuitem_POST;
Object *menuitem_FOLLOWUP;
Object *menuitem_REPLY;
Object *menuitem_BOTH;
Object *menuitem_PDTHIS;
Object *menuitem_MARK;
Object *menuitem_CURRENTDATE;
Object *menuitem_USERS;

Object *app;

Object *grouplistGroup;
Object *grouplistGroup_NLIST;
Object *grouplistGroup_LISTTREE;
MUI_NListtree_TreeNode *tn_folders,*tn_newsgroups;
Object *messageGroup;
Object *messageGroup_NLIST;
Object *messageGroup_LISTTREE;

Object *wnd_main;
Object *wnd_newnewsgroup;
Object *wnd_editng;
Object *wnd_ngadv;
Object *wnd_joinmsgs = NULL;
Object *wnd_account;
Object *wnd_servers;
Object *wnd_killfile;
Object *wnd_newserver;
Object *pages_account;
Object *wnd_groupman;
Object *wnd_search;
Object *wnd_stats;
Object *wnd_choice;
Object *wnd_newuser;
Object *wnd_users;
Object *wnd_login;
Object *wnd_cpwd;
Object *wnd_about;
Object *aboutwin=NULL;

Object *NLIST_groupdata;
Object *LISTTREE_groupdata;
Object *LISTVIEW_groupdata;
Object *NLIST_messagelistdata;
Object *NLISTVIEW_messagelistdata;
Object *LISTTREE_messagelistdata;
Object *LISTTREEVIEW_messagelistdata;
Object *NLIST_groupman;
Object *NLIST_choice;

Object *BT_about_OKAY;

Object *TB_main;

Object *BT_nng_OKAY;
Object *BT_nng_CANCEL;
Object *STR_nng_NAME;
Object *STR_nng_DESC;
Object *CY_nng_DEFSIG;
Object *CM_nng_S;
Object *CY_nng_MAXDL;
Object *STR_nng_MAXDL;
Object *CY_nng_MAXL;
Object *STR_nng_MAXL;
Object *CY_nng_MAXAGE;
Object *STR_nng_MAXAGE;
Object *CY_nng_OFFLINE;
Object *CY_nng_NEWSSERVER;

Object *BT_eng_OKAY;
Object *BT_eng_CANCEL;
Object *STR_eng_NAME;
Object *STR_eng_DESC;
Object *CY_eng_DEFSIG;
Object *CM_eng_S;
Object *CY_eng_MAXDL;
Object *STR_eng_MAXDL;
Object *CY_eng_MAXL;
Object *STR_eng_MAXL;
Object *CY_eng_MAXAGE;
Object *STR_eng_MAXAGE;
Object *CY_eng_OFFLINE;
Object *CY_eng_NEWSSERVER;
Object *GROUP_eng;
Object *TXT_eng_LASTDL;
Object *TXT_eng_FOLDER;

Object *BT_ngadv_OKAY;
Object *BT_ngadv_CANCEL;
Object *CM_ngadv_APPVHD;
Object *STR_ngadv_APPVHD;
Object *CM_ngadv_ALTNAME;
Object *STR_ngadv_ALTNAME;
Object *CM_ngadv_ALTEMAIL;
Object *STR_ngadv_ALTEMAIL;
Object *CM_ngadv_SERVER;
Object *CY_ngadv_SERVER;
Object *CM_ngadv_SERVERPOST;
Object *GROUP_ngadv=NULL;
Object *GROUP_ngadv_SUB=NULL;

Object *BT_joinmsgs_JOIN = NULL;
Object *BT_joinmsgs_CANCEL = NULL;
Object *NLIST_joinmsgs_MSGS = NULL;
Object *STR_joinmsgs_SUBJECT = NULL;

Object *BT_acc_OKAY;
Object *BT_acc_CANCEL;
Object *STR_acc_NAME;
Object *STR_acc_EMAIL;
Object *STR_acc_REALEMAIL;
Object *STR_acc_ORG;
Object *STR_acc_SMTP;
Object *STR_acc_DOMAIN;
Object *CY_acc_TIMEZONE;
Object *CM_acc_USELOCALETZ;
Object *CM_acc_BST;
Object *CY_acc_DATEFORMAT;
Object *CM_acc_LOGGING;
Object *CM_acc_LOGDEL;
Object *CM_acc_VGROUPDL;
Object *CM_acc_NOCONFIRMDEL;
Object *CM_acc_DELONLINE;
Object *CM_acc_CONFIRMQUIT;
Object *CM_acc_QUIETDL;
Object *CM_acc_CHECKFORDUPS;
Object *CM_acc_XNEWS;
Object *STR_acc_NNTP;
Object *STR_acc_PORT;
Object *CM_acc_AUTH;
Object *STR_acc_USER;
Object *STR_acc_PASS;
Object *NLIST_acc_SERVERS;
Object *BT_acc_ADDSERVER;
Object *BT_acc_EDITSERVER;
Object *BT_acc_MAKEDEFSERVER;
Object *BT_acc_MAKEPOSTSERVER;
Object *BT_acc_DELETESERVER;
Object *BT_acc_GETGROUPS;
Object *BT_acc_GETNEWGROUPS;
Object *BT_acc_GROUPMAN;
Object *BT_server_OKAY;
Object *BT_server_CANCEL;
Object *STR_acc_NNTPPOST;
Object *STR_acc_FOLLOWUPTEXT;
Object *POP_acc_CHARSETWRITE;
Object *STR_acc_CHARSETWRITE;
Object *CY_acc_SIG;
//Object *CM_acc_USESIG;
Object *BT_acc_READSIG;
Object *ED_acc_SIG;
Object *SLD_acc_SIG;
Object *STR_acc_LINELENGTH;
Object *CM_acc_REWRAP;
Object *CM_acc_SNIPSIG;
Object *CY_acc_XNO;
Object *NLIST_acc_KILLFILE;
Object *BT_acc_NEWKILLADD;
Object *STR_acc_NEWKILLHEAD;
Object *STR_acc_NEWKILLTEXT;
Object *STR_acc_NEWKILLGROUP;
Object *BT_acc_NEWKILL;
Object *BT_acc_DELKILL;
Object *BT_acc_DUPKILL;
Object *CM_acc_SIZEKILL;
Object *CY_acc_EXPIREKILL;
Object *STR_acc_EXPIREKILL;
//Object *CY_acc_TYPEKILL;
Object *CY_acc_MATCHKILL;
Object *CY_acc_ACTIONKILL;
Object *CM_acc_SKIPKILL;
Object *CY_wiz_EXPIREKILL;
Object *STR_wiz_EXPIREKILL;
Object *CM_acc_LISTFLAGS;
Object *CM_acc_LISTSUBJECT;
Object *CM_acc_LISTDATE;
Object *CM_acc_LISTFROMGROUP;
Object *CM_acc_LISTSIZE;
Object *CM_acc_LISTLINES;
Object *NLIST_acc_MIMEPREFS;
Object *POP_acc_MIME;
Object *LIST_acc_MIME;
Object *STR_acc_MIME;
Object *POP_acc_MIMEVIEW;
Object *STR_acc_MIMEVIEW;
Object *POP_acc_MIMEDEF;
Object *STR_acc_MIMEDEF;
Object *BT_acc_MIMENEW;
Object *BT_acc_MIMEDEL;
Object *CY_acc_READHEADER;
Object *STR_acc_READHEADER;
Object *PEN_acc_TEXT_QUOTE2;
Object *PEN_acc_TEXT_COL;
Object *CM_acc_MULTIPLEVWS;

Object *STR_groupman_FIND;
Object *BT_groupman_SUB;
Object *BT_groupman_GET;
Object *NLIST_search_NG;
Object *BT_search_START;
Object *CY_search_WHERE;
Object *STR_search_HEAD;
Object *STR_search_WHAT;
Object *CM_search_CASESENS;
Object *NLIST_search_RES;

Object *NLIST_stats_NG;
Object *BT_stats_START;
Object *CY_stats_WHAT;
Object *NLIST_stats_RES;

Object *BT_choice_SAVE;
Object *BT_choice_DISP;
Object *BT_choice_CANC;

Object *TXT_newuser_INFO;
Object *BT_newuser_OKAY;
Object *BT_newuser_CANCEL;
Object *STR_newuser_USER;
Object *STR_newuser_PASS;
Object *CM_newuser_PASS;
Object *STR_newuser_DATALOC;
Object *POP_newuser_DATALOC;
Object *CM_newuser_SUP;
Object *CM_newuser_COPYPREFS;

Object *NLIST_users_LIST;
Object *BT_users_NEW;
Object *BT_users_DELETE;

Object *BT_login_OKAY;
Object *BT_login_CANCEL;
Object *STR_login_USER;
Object *STR_login_PASS;

Object *TXT_cpwd_INFO;
Object *BT_cpwd_OKAY;
Object *BT_cpwd_CANCEL;
Object *STR_cpwd_PASS;
Object *CM_cpwd_PASS;

/* If this is changed, the enum TB_Index should be updated appropriately.
 */
static MUIP_Toolbar_Description TB_main_desc[] = {
	{TDT_BUTTON,	'R',	0,		"_Read",			"Read the selected message", 0},
	{TDT_BUTTON,	'X',	0,		"E_xport",		"View or Save parts of the\nselected message\n(attachments)", 0},
	{TDT_BUTTON,	'M',	0,		"_Move",			"Move the selected message(s)\nto another folder", 0},
	{TDT_BUTTON,	'C',	0,		"_Copy",			"Copy the selected message(s)\nto another folder", 0},
	{TDT_BUTTON,	'D',	0,		"_Delete",		"Delete the selected\nmessage(s)", 0},
	{TDT_BUTTON,	'K',	0,		"_Kill",			"Add a new killfile based on\nthe selected message", 0},
	{TDT_SPACE, NULL, NULL, NULL, NULL, NULL},
	{TDT_BUTTON,	'P',	0,		"_Post",			"Post a new message", 0},
	{TDT_BUTTON,	'F',	0,		"_Followup",	"Followup the selected\nmessage (to the newsgroup)", 0},
	{TDT_BUTTON,	'E',	0,		"_Edit",			"Edit the selected message", 0},
	{TDT_SPACE, NULL, NULL, NULL, NULL, NULL},
	{TDT_BUTTON,	NULL,	0,		"Fetch",			"Fetch news", 0},
	{TDT_BUTTON,	NULL,	0,		"Send",			"Send news", 0},
	{TDT_SPACE, NULL, NULL, NULL, NULL, NULL},
	{TDT_BUTTON,	NULL,	0,		"Search",		"Search for a message", 0},
	{TDT_BUTTON,	NULL,	0,		"Settings",		"Program settings", 0},
	{TDT_BUTTON,	NULL,	0,		"Killfile",		"View and edit the killfile", 0},
	{TDT_END, NULL, NULL, NULL, NULL, NULL}
};

/* Pages on the Program Settings window (wnd_acc)
 */
static char *Pages_acc[]   = {"Accounts","Servers","Write","Read","Lists","MIME",NULL };
const int ACCSIGPAGE=2; // must be the Write page !

/* The Date Format cycle gadget under Program Settings
 */
static char *CYA_acc_dateformat[] = {
	"DD-MMM-YY","DD-MM-YY",NULL
};

/* The Signatures cycle gadget under Program Settings
 */
static char *CYA_acc_sigs[] = {
	"Signature 1","Signature 2","Signature 3","Signature 4","Signature 5","Signature 6","Signature 7","Signature 8",NULL
};

/* The cycle gadget for Headers to Display under Program Settings
 */
static char *CYA_acc_readheader[] = {
	"None","Selected","Full",NULL
};

/* The Discard cycle gadget under New Newsgroup
 */
static char *CYA_nng_maxage[] = {
	"Don't Discard Messages","Discard After x Days:",NULL
};

/* The Offline/Online cycle gadget under New Newsgroup
 */
static char *CYA_nng_offline[] = {
	"Offline Reading","Online Reading",NULL
};

/* The newsservers cycle gadget under New Newsgroup
 */
static char *CYA_nng_newsservers[] = {
	"Newsserver 1","Newsserver 2","Newsserver 3","Newsserver 4","Newsserver 5","Newsserver 6","Newsserver 7","Newsserver 8",NULL
};

/* The timezone cycle gadget under New Newsgroup
 */
static char *CYA_acc_timezone[] = {
	"GMT-12","GMT-11","GMT-10","GMT-9","GMT-8 (PDT)","GMT-7 (MDT)","GMT-6 (CMT)","GMT-5 (EST)","GMT-4 (ADT)","GMT-3","GMT-2","GMT-1",
	"GMT (GMT)","GMT+1 (MET)","GMT+2 (EET)","GMT+3","GMT+4","GMT+5","GMT+6","GMT+7","GMT+8 (PST)","GMT+9","GMT+10","GMT+11","GMT+12",NULL
};

/* The x-no-archive cycle gadget under New Newsgroup
 */
static char *CYA_acc_xno[] = {
	"Never","Always","Only if in followed up to post",NULL
};

/* The Expire cycle gadget under the KillFile window (wnd_killfile)
 */
static char *CYA_acc_expirekill[] = {
	"Never Expire","Expire x days from creation:","Expire x days from last usage:",NULL
};

/* The Match cycle gadget under the KillFile window (wnd_killfile)
 */
static char *CYA_acc_matchkill[] = {
	"Contains", "Does Not Contain", NULL
};

/* The Action cycle gadget under the KillFile window (wnd_killfile)
 */
static char *CYA_acc_actionkill[] = {
	"Kill", "Mark As Important", NULL
};

/* The Maximum Number to Download cycle gadget under New Newsgroup
 */
static char *CYA_nng_maxdl[] = {
	"Unlimited Messages per Download","Maximum # of Messages to Download:",NULL
};

/* The Maximum Length cycle gadget under New Newsgroup
 */
static char *CYA_nng_maxl[] = {
	"Download messages of any length","Skip messages longer than this # of lines:",NULL
};

/* The Where cycle gadget under the Search window (wnd_search)
 */
static char *CYA_search_where[] = {
	"From","Newsgroups","Subject","MessageID","Header", "Message Body", "Entire Message",NULL
};
enum {
	SEARCH_FROM = 0, SEARCH_NEWSGROUPS = 1, SEARCH_SUBJECT = 2, SEARCH_MESSAGEID = 3, SEARCH_HEADER = 4, SEARCH_BODY = 5, SEARCH_ALL = 6
};

/* The What cycle gadget under the Stats window (wnd_stats)
 */
static char *CYA_stats_what[] = {
	"By Person","By Subject","By X-Newsreader",NULL
};

/* For the newsserver cycle gadget (allocated dynamically) under the Newsgroup Advanced Settings window (wnd_ngadv)
 */
char **CYA_ngadv_server = NULL;
int   *server_list      = NULL;

/*SAVEDS ASM LONG StrObjFunc(REG(a2) Object *pop,REG(a1) Object *str) {*/
LONG HOOK2( StrObjFunc, Object *, pop, a2, Object *, str, a1 )
	char *x = NULL,*s = NULL;
	int i = 0;

	get(str,MUIA_String_Contents,&s);

	for (i=0;;i++) {
		DoMethod(pop,MUIM_List_GetEntry,i,&x);
		if (!x) {
			set(pop,MUIA_List_Active,MUIV_List_Active_Off);
			break;
		}
		else if (!stricmp(x,s)) {
			set(pop,MUIA_List_Active,i);
			break;
		}
	}
	return(TRUE);
}

/*SAVEDS ASM VOID ObjStrAccFunc(REG(a2) Object *pop,REG(a1) Object *str) {*/
VOID HOOK2( ObjStrAccFunc, Object *, pop, a2, Object *, str, a1 )
	char *x = NULL;
	DoMethod(pop,MUIM_List_GetEntry,MUIV_List_GetEntry_Active,&x);
	set(str,MUIA_String_Contents,x);
	int entries = 0;
	MIMEPrefs * mime = NULL;
	get(NLIST_acc_MIMEPREFS,MUIA_NList_Entries,&entries);
	if(entries>0) {
		int val = 0;
		get(NLIST_acc_MIMEPREFS,MUIA_NList_Active,&val);
		if(val!=MUIV_NList_Active_Off) {
			DoMethod(NLIST_acc_MIMEPREFS,MUIM_NList_GetEntry,MUIV_NList_GetEntry_Active,&mime);
			strncpy(mime->type,x,MIMEPREFS_TYPE_LEN);
			mime->type[MIMEPREFS_TYPE_LEN] = '\0';
			DoMethod(NLIST_acc_MIMEPREFS,MUIM_NList_Redraw,MUIV_NList_Redraw_Active);
		}
	}
}

/*SAVEDS ASM VOID ObjStrAcc2Func(REG(a2) Object *pop,REG(a1) Object *str) {*/
VOID HOOK2( ObjStrAcc2Func, Object *, pop, a2, Object *, str, a1 )
	char *x = NULL;
	DoMethod(pop,MUIM_List_GetEntry,MUIV_List_GetEntry_Active,&x);
	set(str,MUIA_String_Contents,x);
	int entries = 0;
	MIMEPrefs * mime = NULL;
	MIMEPrefs * mime2 = new MIMEPrefs;
	get(NLIST_acc_MIMEPREFS,MUIA_NList_Entries,&entries);
	if(entries>0) {
		int val = 0;
		get(NLIST_acc_MIMEPREFS,MUIA_NList_Active,&val);
		if(val!=MUIV_NList_Active_Off) {
			DoMethod(NLIST_acc_MIMEPREFS,MUIM_NList_GetEntry,MUIV_NList_GetEntry_Active,&mime);
			*mime2=*mime;
			strncpy(mime2->viewer,x,MIMEPREFS_VIEWER_LEN);
			mime2->viewer[MIMEPREFS_VIEWER_LEN] = '\0';
			DoMethod(NLIST_acc_MIMEPREFS,MUIM_NList_ReplaceSingle,mime2,MUIV_NList_Insert_Active,NOWRAP,ALIGN_LEFT);
			DoMethod(NLIST_acc_MIMEPREFS,MUIM_NList_Redraw,MUIV_NList_Redraw_Active);
		}
	}
}

/*SAVEDS ASM VOID ObjStrAcc3Func(REG(a2) Object *pop,REG(a1) Object *str) {*/
VOID HOOK2( ObjStrAcc3Func, Object *, pop, a2, Object *, str, a1 )
	char *x = NULL;
	DoMethod(pop,MUIM_List_GetEntry,MUIV_List_GetEntry_Active,&x);
	set(str,MUIA_String_Contents,x);
}

/*SAVEDS ASM VOID ObjStrNewuserFunc(REG(a2) Object *pop,REG(a1) Object *str) {*/
VOID HOOK2( ObjStrNewuserFunc, Object *, pop, a2, Object *, str, a1 )
	char *x;
	DoMethod(pop,MUIM_List_GetEntry,MUIV_List_GetEntry_Active,&x);
	set(str,MUIA_String_Contents,x);
}

/*SAVEDS ASM VOID WindowFunc(REG(a2) Object *pop,REG(a1) Object *win) {*/
VOID HOOK2( WindowFunc, Object *, pop, a2, Object *, win, a1 )
	set(win,MUIA_Window_DefaultObject,pop);
}

MUI_CustomClass *editor_mcc = NULL;
int cy_current_sig=0;
BOOL registered = FALSE;
int regID = 0;
int sorttype_search=0;
int sorttypedir_search=1; //1=down,-1=up
int sorttype_stats=0; // 0=value, 1=freq
int sorttypedir_stats=1; //1=down,-1=up
int stats_what=0;
int t_abort=FALSE;
int t_save=FALSE;
int t_disp=FALSE;
int prefsversion=4;
/* version history:
	4 : 1.30
	*/
BOOL FORCEPATCH1=FALSE;
BOOL accountpage=FALSE;
BOOL delete_dis=FALSE;
//BOOL downloading_headers=FALSE;
int newuseradded=0; // 0=not yet,1=yes,2=cancelled
ULONG signal = 0;
BOOL running = TRUE;

int nextID=0;
int nextServerID=1;

short Account::SNIPSIG = 1;
short Account::LOGGING = 2;
short Account::LOGDEL = 4;
short Account::NODELONLINE = 8;
short Account::QUIETDL = 16;
short Account::NOCONFIRMQUIT = 32;
short Account::CHECKFORDUPS = 64;

short Account::LISTUPDATE = 1;
short Account::LISTFLAGS = 2;
short Account::LISTSUBJECT = 4;
short Account::LISTDATE = 8;
short Account::LISTFROMGROUP = 16;
short Account::LISTSIZE = 32;
short Account::LISTLINES = 64;

BOOL nlisttree = TRUE;
Account account;
char *sigs[NSIGS];
int nng_defserver = 0;
Server *groupman_server = NULL;
Regist * regist = NULL;
GroupData * ng_edit=NULL;
GroupData * ng_editadv=NULL;
GroupData *old_gdata=NULL;
GroupData *c_gdata=NULL; // currently being displayed
GroupData *v_gdata=NULL; // set this to the gdata we wish to view (for read_index())
int gdata_readID=-100;
Server *editServer=NULL; // server currently being edited (NULL if none)
library ASLlib("asl.library",0); // constructor opens libraries
library Localelib("locale.library",0); // constructor opens libraries

char tempStatusText[256]="";
const int TAB=4;

LONG xget(Object *obj,ULONG attribute) {
	LONG x;
	get(obj,attribute,&x);
	return(x);
}

char * getstr(Object *obj) {
	return( (char *)xget(obj,MUIA_String_Contents));
}

Library * SocketBase=NULL;

/* library constructor - opens an AmigaOS Library
 */
library::library(char * name,int version) {
	if((Base = OpenLibrary(name,version)) == NULL)
		printf("Error - Cannot open library!\n");
}

/* library destructor - closes the Library
 */
library::~library() {
	if(Base) {
		CloseLibrary(Base);
		Base=NULL;
	}
}

/* KillFile constructor - sets the timestamps to now
 */
KillFile::KillFile() {
	nLog("KillFile() constructor called\n");
	memset(this,0,sizeof(KillFile));
	DateStamp(&ds);
	DateStamp(&lastused);
	expiretype = 0;
	expire = 0;
	//type = 0;
	match = 0;
	action = 0;
	carryon = 0;
	*header = '\0';
	*text = '\0';
	*ngroups = '\0';
}

/* Gets the current timezone offset from GMT, either as chosen by the user,
 * or uses the Locale library if he prefers
 */
int getGMTOffset() {
	if(account.uselocaletz) {
		Locale * locale = OpenLocale(NULL);
		if(locale!=NULL) {
			int ttz=-(int)(locale->loc_GMTOffset/60);
			return ttz;
		}
	}
	return account.timezone;
}

/* Makes sure certain buttons and menu items are enabled or disabled as
 * necessary.
 * Also sets up the 'bubble help' for the message list.
 */
void setEnabled() {
	nLog("setEnabled() called\n");
	int active = 0;
	BOOL s,s_edit,s_super,s_cancel,s_undel,s_kill,s_changedate,s_gns;
	getMdataActivePos(&active);
	if(active==MUIV_NList_Active_Off)
		s=TRUE;
	else
		s=FALSE;
	// turn off those for irrelevant folders
	GroupData * gdata = NULL;
	getGdataDisplayed(&gdata);
	//printf("***%d\n",gdata->ID);
	s_edit = s;
	if(gdata->ID!=-1 && gdata->ID!=-2)
		s_edit = TRUE;
	s_super = s;
	s_cancel = s;
	if(gdata->ID!=-2) {
		s_super = TRUE;
		s_cancel = TRUE;
	}
	s_undel = s;
	if(gdata->ID!=-3)
		s_undel = TRUE;
	s_kill = s;
	if(gdata->ID<0)
		s_kill = TRUE;
	s_gns = gdata->ID < 0;
	s_changedate = s;
	if(gdata->ID != -1)
		s_changedate = TRUE;

	DoMethod(TB_main,MUIM_Toolbar_Set,TB_READ,MUIV_Toolbar_Set_Ghosted,s);
	DoMethod(TB_main,MUIM_Toolbar_Set,TB_EXPORT,MUIV_Toolbar_Set_Ghosted,s);
	DoMethod(TB_main,MUIM_Toolbar_Set,TB_MOVE,MUIV_Toolbar_Set_Ghosted,s);
	DoMethod(TB_main,MUIM_Toolbar_Set,TB_COPY,MUIV_Toolbar_Set_Ghosted,s);
	DoMethod(TB_main,MUIM_Toolbar_Set,TB_DELETE,MUIV_Toolbar_Set_Ghosted,s);
	DoMethod(TB_main,MUIM_Toolbar_Set,TB_KILL,MUIV_Toolbar_Set_Ghosted,s_kill);
	DoMethod(TB_main,MUIM_Toolbar_Set,TB_POST,MUIV_Toolbar_Set_Ghosted,FALSE);
	DoMethod(TB_main,MUIM_Toolbar_Set,TB_FOLLOWUP,MUIV_Toolbar_Set_Ghosted,s);
	DoMethod(TB_main,MUIM_Toolbar_Set,TB_EDIT,MUIV_Toolbar_Set_Ghosted,s_edit);
	s=!s;
	s_edit = !s_edit;
	s_super = !s_super;
	s_cancel = !s_cancel;
	s_undel = !s_undel;
	s_kill = !s_kill;
	s_gns = !s_gns;
	s_changedate = !s_changedate;
	set(menuitem_GETNEWSSINGLE,MUIA_Menuitem_Enabled,s_gns);
	set(menuitem_READ,MUIA_Menuitem_Enabled,s);
	set(menuitem_EDIT,MUIA_Menuitem_Enabled,s_edit);
	set(menuitem_SUPER,MUIA_Menuitem_Enabled,s_super);
	set(menuitem_CANCEL,MUIA_Menuitem_Enabled,s_cancel);
	set(menuitem_DELMESS,MUIA_Menuitem_Enabled,s);
	set(menuitem_UNDELMESS,MUIA_Menuitem_Enabled,s_undel);
	set(menuitem_EXP,MUIA_Menuitem_Enabled,s);
	set(menuitem_MOVE,MUIA_Menuitem_Enabled,s);
	set(menuitem_COPY,MUIA_Menuitem_Enabled,s);
	set(menuitem_KILLMESS,MUIA_Menuitem_Enabled,s_kill);
	set(menuitem_YAMADDRESS,MUIA_Menuitem_Enabled,s);
	set(menuitem_POST,MUIA_Menuitem_Enabled,TRUE);
	set(menuitem_FOLLOWUP,MUIA_Menuitem_Enabled,s);
	set(menuitem_REPLY,MUIA_Menuitem_Enabled,s);
	set(menuitem_BOTH,MUIA_Menuitem_Enabled,s);
	set(menuitem_PDTHIS,MUIA_Menuitem_Enabled,s);
	set(menuitem_MARK,MUIA_Menuitem_Enabled,s);
	set(menuitem_CURRENTDATE,MUIA_Menuitem_Enabled,s_changedate);

	static char helptext[4096] = "";
	MessageListData *mdata = NULL;
	getMdataActive(&mdata);
	if(mdata != NULL) {
		//if(*mdata->datec == '\0')
		//	sprintf(mdata->datec,"%s %s",mdata->c_date,mdata->c_time);
		//printf(":::%d : %s\n",mdata->ID,mdata->subject);

		char filename[300] = "";
		getFilePath(filename,gdata->ID,mdata->ID);
		
		//char newsgroups[MAXLINE] = "unknown";
		//get_newsgroups(newsgroups,gdata->ID,mdata->ID);
		NewMessage newmess;
		get_refs(&newmess,filename,GETREFS_NONE,TRUE);

		sprintf(helptext,
			"From: %s\nSubject: %s\nDate: %s %s\nNewsgroups: %s\nSize: %d\n# of Lines: %d\nFilename: %s%s%s%s%s\n",
			//mdata->from,
			newmess.from,
			//mdata->subject,
			newmess.subject,
			mdata->c_date,
			mdata->c_time,
			//mdata->newsgroups,
			//newsgroups,
			newmess.newsgroups,
			mdata->size,
			mdata->flags[8],
			filename,
			mdata->flags[1] ? "\nUnread message" : "",
			mdata->flags[0] ? "\nMessage is Held" : "",
			mdata->flags[10] ? "\nYou have replied to this message" : "",
			mdata->flags[12] ? "\nBody not yet downloaded" : ""
		);
	}
	else
		strcpy(helptext,"No message selected");

	set(NLIST_messagelistdata,MUIA_ShortHelp,helptext);
	if(nlisttree)
		set(LISTTREE_messagelistdata,MUIA_ShortHelp,helptext);

}

void setGdataHelpText(GroupData *gdata) {
	nLog("setGdataHelpText((GroupData *)%d) called\n",gdata);
	static char helptext[4096] = "";
	if(gdata != NULL) {
		char filename[300] = "";
		getFolderPath(filename,gdata->ID);
		char lastdl[256] = "";
		if(gdata->ID >= 0) {
			strcpy(lastdl,"\nLast Downloaded: ");
			DateHandler::get_date(&lastdl[ strlen(lastdl) ],getGMTOffset(),account.bst,gdata->lastdlds);
		}
		Server *server = (gdata->ID >= 0) ? getServer(gdata->serverID) : NULL;

		sprintf(helptext,
			"%s\n# of Messages: %d\n# of Unread Messages: %d%s%s%s%s%s\nFolder Location: %s",
			gdata->name,
			gdata->nummess,
			gdata->num_unread,
			gdata->ID < 0 ? "" : (gdata->flags[5] ? "\nOnline Reading" : "\nOffline Reading"),
			server == NULL ? "" : "\nUsing ", server == NULL ? "" : server->nntp,
			gdata->ID < 0 ? "" : (gdata->s ? "\nYou are Subscribed to this group." : ""),
			lastdl,
			filename
		);
	}
	else
		strcpy(helptext,"No group selected");

	set(NLIST_groupdata,MUIA_ShortHelp,helptext);
	if(nlisttree)
		set(LISTTREE_groupdata,MUIA_ShortHelp,helptext);
}

void sleepAll(BOOL sleep) {
	set(wnd_main,MUIA_Window_Sleep,sleep);
	ViewWindow::sleepAll(sleep);
	WriteWindow::sleepAll(sleep);
	//printf("sleep is : %d\n",sleep);
}

void delete_file(GroupData * gdata,MessageListData * mdata) {
	char filename[300] = "";
	getFilePath(filename,gdata->ID,mdata->ID);
	DeleteFile(filename);
}

void delete_file_n(GroupData * gdata,MessageListData * mdataptr,int n) {
	char filename[300] = "";
	if(gdata->ID==-1)
		sprintf(filename,"NewsCoasterData:outgoing/news_");
	else if(gdata->ID==-2)
		sprintf(filename,"NewsCoasterData:sent/news_");
	else if(gdata->ID==-3)
		sprintf(filename,"NewsCoasterData:deleted/news_");
	else if(gdata->ID>=0)
		sprintf(filename,"NewsCoasterData:folder_%d/news_",gdata->ID);
	char *ptr = &filename[ strlen(filename) ];
	for(int i=0;i<n;i++) {
		sprintf(ptr,"%d",mdataptr[i].ID);
		DeleteFile(filename);
	}
}

BOOL changedate(GroupData *gdata,MessageListData *mdata,char *date,void *source) {
	nLog("changedate((GroupData *)%d,(MessageListData *)%d,(char *)%s,(void *)%d) called\n",gdata,mdata,date,source);
	char buffer[300] = "";
	char buffer2[300] = "";
	char line[MAXLINE] = "";
	getFilePath(buffer,gdata->ID,mdata->ID);
	sprintf(buffer2,"%s.new",buffer);
	DeleteFile(buffer2);

	BPTR file=Open(buffer,MODE_READWRITE);

	BPTR lock2=Lock(buffer2,ACCESS_WRITE);
	BPTR file2=Open(buffer2,MODE_NEWFILE);
	
	BOOL rtn = FALSE;
	
	if(file!=NULL && file2!=NULL) {
		rtn = TRUE;
		for(;;) {
			if(!FGets(file,line,MAXLINE))
				break;
			if(strncmp(line,"Date:",5)==0) {
				char dateline[256] = "";
				sprintf(dateline,"Date: %s\n",date);
				Write(file2,dateline,strlen(dateline));
			}
			else
				Write(file2,line,strlen(line));
		}
	}
	if(file2)
		Close(file2);
	if(lock2)
		UnLock(lock2);
	if(file)
		Close(file);
	//if(lock)
	//	UnLock(lock);
	
	if(rtn) {
		DeleteFile(buffer);
		Rename(buffer2,buffer);
		//printf("buffer : %s\n",buffer);
		//printf("buffer2: %s\n",buffer2);
		//mdata->ID = newID;
		write_index_update(gdata,mdata,source);
	}
	
	return rtn;
}

void archiveGroup(GroupData *gdata,char *filename) {
	nLog("archiveGroup((GroupData *)%d,(char *)%s) called\n",gdata,filename);
	MessageListData * mdata=NULL;
	if(gdata==NULL)
		return;
	int k = 0;
	int entries = 0;
	BPTR file=NULL;
	BPTR file2=NULL;
	BPTR lock2=NULL;

	char filename2[128]="NewsCoasterData:";
	int offset = strlen(filename2);
	if(gdata->ID==-1)
		sprintf(&filename2[offset],"outgoing/news_");
	else if(gdata->ID==-2)
		sprintf(&filename2[offset],"sent/news_");
	else if(gdata->ID==-3)
		sprintf(&filename2[offset],"deleted/news_");
	else if(gdata->ID>=0)
		sprintf(&filename2[offset],"folder_%d/news_",gdata->ID);
	offset = strlen(filename2);

	char *big_buffer = new char[big_bufsize_g + 1];
	char divide[1024]="";
	get(NLIST_messagelistdata,MUIA_NList_Entries,&entries);
	//archive folder
	DeleteFile(filename);
	file=Open(filename,MODE_NEWFILE);
	if(file) {
		StatusWindow *statusWindow = new StatusWindow(app,"Archiving..");
		sleepAll(TRUE);
		Flush(file);
		if(entries>0) {
			strcpy(divide,"From ???@??? ");
			for(k=0;k<entries;k++) {
				DoMethod(app,MUIM_Application_InputBuffered);
				if(k % 32 == 0) {
					do_input();
					if(statusWindow->isAborted()==TRUE || running==FALSE)
						break;
					sprintf(status_buffer_g,"Archiving.. (%d/%d)",k+1,entries);
					statusWindow->setText(status_buffer_g);
				}
				DoMethod(NLIST_messagelistdata,MUIM_NList_GetEntry,k,&mdata);
				if(mdata->flags[12]) {
					// online message - skip
					continue;
				}
				sprintf(&filename2[offset],"%d",mdata->ID);
				file2=NULL;
				//lock2=Lock(filename2,ACCESS_READ);
				//if(lock2)
					file2=Open(filename2,MODE_OLDFILE);
				if(file2==NULL) {
					nLog("Error in archiveGroup()! - Can't open file: %s\n",filename2);
					sprintf(status_buffer_g,"\33cUnable to open file:\n%s",filename2);
					MUI_RequestA(app,0,0,"Error","_Okay",status_buffer_g,0);
					if(lock2) {
						UnLock(lock2);
						lock2=NULL;
					}
				}
				else {
					// write file to archive
					DateHandler::get_date_mailbox(&divide[13],mdata->ds);
					Write(file,divide,25 + 12);
					Write(file,"\n",1);
					int read = 0;
					/*while( (read=Read(file2,buffer,bufsize))>0 ) {
						Write(file,buffer,read);
					}*/
					while( (read=Read(file2,big_buffer,big_bufsize_g))>0 ) {
						Write(file,big_buffer,read);
					}
					Close(file2);
					file2=NULL;
					Write(file,"\n",1);
				}
			}
		}
		sleepAll(FALSE);
		delete statusWindow;
	}
	else {
		sprintf(status_buffer_g,"Couldn't open file %s to write to.\n",filename);
		nLog(status_buffer_g);
		MUI_RequestA(app,0,0,"Error","_Okay",status_buffer_g,0);
	}
	if(file) {
		Close(file);
		file=NULL;
	}
	delete [] big_buffer;
}

int parse_index_version(char *version) {
	nLog("parse_index_version((char *)%s) called\n",version);
	version++;
	int v = atoi(version);
	nLog("  returning %d\n",v);
	return v;
}

void clearThreadView() {
	nLog("clearThreadView() called\n");
	DoMethod(LISTTREE_messagelistdata,MUIM_NListtree_Remove,MUIV_NListtree_Remove_ListNode_Root,MUIV_NListtree_Remove_TreeNode_All,0);
}

void threadView() {
	nLog("threadView() called\n");
	if(account.mdata_view!=1)
		return;
	// takes messages from NLIST_messagelistdata, and inserts into LISTTREE_messagelistdata
	int entries = 0;
	BOOL cont = FALSE;
	int skipped = 0,start = 0;
	DoMethod(NLIST_messagelistdata,MUIM_NList_Sort);
	get(NLIST_messagelistdata,MUIA_NList_Entries,&entries);
	set(wnd_main,MUIA_Window_Sleep,TRUE);
	setMdataQuiet(TRUE);

	MessageListData * mdata = NULL;
	MessageListData * current_mdata = NULL;
	getMdataActive(&current_mdata);
	//printf("%d\n",current_mdata);
	if(current_mdata != NULL && get_mdataptr_pos(current_mdata) == -1)
		current_mdata = NULL; // message no longer exists in list - we don't want to reference it, in cases it's been deleted!
	//printf("-->%d\n",current_mdata);

	clearThreadView();

	if(entries>0) {
		//MUI_NListtree_TreeNode ** tnptr = (MUI_NListtree_TreeNode **)AllocVec(sizeof(MUI_NListtree_TreeNode *)*entries,MEMF_PUBLIC|MEMF_CLEAR);
		MUI_NListtree_TreeNode ** tnptr = new MUI_NListtree_TreeNode *[entries];
		int *positions = new int[entries];
		int i=0;
		for(i=0;i<entries;i++) {
			tnptr[i] = NULL;
			
			DoMethod(NLIST_messagelistdata,MUIM_NList_GetEntry,i,&mdata);
			if(*mdata->lastref == '\0')
				positions[i] = -1;
			else
				get_mdata_pos(&positions[i],mdata->lastref);
		}
		int count = 0;
		int *stack = new int[entries];
		for(i=0;i<entries;i++) {
			if(tnptr[i] == NULL) {
				int pos = positions[i];
				if( pos == -1 || pos == i ) {
					// new thread
					DoMethod(NLIST_messagelistdata,MUIM_NList_GetEntry,i,&mdata);
					tnptr[i]=(MUI_NListtree_TreeNode *)DoMethod(LISTTREE_messagelistdata,MUIM_NListtree_Insert,"",mdata,MUIV_NListtree_Insert_ListNode_Root,MUIV_NListtree_Insert_PrevNode_Tail,TNF_LIST);
					count++;
				}
				else {
					int n = 0;
					stack[n++] = i;
					for(;;) {
						stack[n++] = pos;
						if(pos == -1 || tnptr[pos] != NULL)
							break;

						int new_pos = positions[pos];
						if(new_pos == pos) {
							stack[n++] = pos;
							break;
						}
						pos = new_pos;
					}
					int parent = pos;
					for(int j=n-2;j>=0;j--) {
						int p = stack[j];
						if(parent == -1 || parent == p) {
							DoMethod(NLIST_messagelistdata,MUIM_NList_GetEntry,p,&mdata);
							tnptr[p]=(MUI_NListtree_TreeNode *)DoMethod(LISTTREE_messagelistdata,MUIM_NListtree_Insert,"",mdata,MUIV_NListtree_Insert_ListNode_Root,MUIV_NListtree_Insert_PrevNode_Tail,TNF_LIST);
							count++;
						}
						else {
							DoMethod(NLIST_messagelistdata,MUIM_NList_GetEntry,p,&mdata);
							tnptr[p]=(MUI_NListtree_TreeNode *)DoMethod(LISTTREE_messagelistdata,MUIM_NListtree_Insert,"",mdata,tnptr[parent],MUIV_NListtree_Insert_PrevNode_Tail,TNF_LIST);
							count++;
						}
						parent = p;
					}
				}
			}
		}
		if(count != entries) {
			printf("count %d differs from entries %d !\n",count,entries);
			nLog("count %d differs from entries %d !\n",count,entries);
		}
		delete [] tnptr;
		delete [] positions;
		delete [] stack;

		if(current_mdata != NULL) {
			//printf("-->%d : %s\n",current_mdata->ID,current_mdata->subject);
			set_mdata(current_mdata);
		}
	}
	DoMethod(LISTTREE_messagelistdata,MUIM_NList_ColWidth,MUIV_NList_ColWidth_All,MUIV_NList_ColWidth_Default);
	setMdataQuiet(FALSE);
	set(wnd_main,MUIA_Window_Sleep,FALSE);
}

void update_screen_title(GroupData *gdata) {
	nLog("update_screen_title((GroupData *)%d) called\n",gdata);
	if(*gdata->desc==NULL)
		sprintf(scrtitle,"%s - Reading %s [%d messages - %d unread]",base_scrtitle,gdata->name,gdata->nummess,gdata->num_unread);
	else
		sprintf(scrtitle,"%s - Reading %s [%d messages - %d unread]",base_scrtitle,gdata->desc,gdata->nummess,gdata->num_unread);
	set(wnd_main,MUIA_Window_ScreenTitle,scrtitle);
}

void set_and_read(int gID) {
	nLog("set_and_read((int)%d) called\n",gID);
	GroupData * gdata2=NULL;
	getGdataDisplayed(&gdata2);
	if(gdata2->ID != gID) {
		set_gdata(gID);
		read_index();
	}
}

void set_and_read(GroupData * gdata) {
	nLog("set_and_read((GroupData *)%d) called\n",gdata);
	set_and_read(gdata->ID);
}

void set_and_read(char * name) {
	nLog("set_and_read((char *)%s) called\n",name);
	GroupData * gdata = NULL;
	getGdataDisplayed(&gdata);
	//if(gdata->name != name) {
	if(stricmp(gdata->name,name) != 0) {
		set_gdata(name);
		read_index();
	}
}

BOOL exfile(MIMEType * mime) {
	nLog("exfile((MIMEType *)%d) called\n",mime);
	BPTR lock=NULL;
	BOOL okay=FALSE;
	FileInfoBlock * fib=(FileInfoBlock *)AllocDosObject(DOS_FIB,NULL);
	int len;
	if(!fib)
	{
		printf("Error! Cannot allocate fib - exfile()\n");
		return FALSE;
	}
	lock=Lock(mime->file,ACCESS_READ);
	if(lock)
	{
		if(Examine(lock,fib))
		{
			strncpy(mime->shortname,fib->fib_FileName,MIMETYPE_SHORTNAME_LEN);
			mime->shortname[MIMETYPE_SHORTNAME_LEN] = '\0';
			mime->size=fib->fib_Size;
			*mime->type = '\0';
			len = strlen(mime->shortname);
			if(stricmp(&mime->shortname[len-4],".txt")==0)
				strcpy(mime->type,"text/plain");
			else if(stricmp(&mime->shortname[len-5],".html")==0)
				strcpy(mime->type,"text/html");
			else if(stricmp(&mime->shortname[len-4],".htm")==0)
				strcpy(mime->type,"text/html");
			else if(stricmp(&mime->shortname[len-4],".shtml")==0)
				strcpy(mime->type,"text/html");
			else if(stricmp(&mime->shortname[len-6],".guide")==0)
				strcpy(mime->type,"text/x-aguide");
			else if(stricmp(&mime->shortname[len-4],".exe")==0)
				strcpy(mime->type,"application/octet-stream");
			else if(stricmp(&mime->shortname[len-3],".ps")==0)
				strcpy(mime->type,"application/postscript");
			else if(stricmp(&mime->shortname[len-4],".lha")==0)
				strcpy(mime->type,"application/x-lha");
			else if(stricmp(&mime->shortname[len-4],".lzx")==0)
				strcpy(mime->type,"application/x-lzx");
			else if(stricmp(&mime->shortname[len-4],".zip")==0)
				strcpy(mime->type,"application/x-zip");
			else if(stricmp(&mime->shortname[len-5],".jpeg")==0)
				strcpy(mime->type,"image/jpeg");
			else if(stricmp(&mime->shortname[len-4],".jpg")==0)
				strcpy(mime->type,"image/jpeg");
			else if(stricmp(&mime->shortname[len-4],".png")==0)
				strcpy(mime->type,"image/png");
			else if(stricmp(&mime->shortname[len-4],".gif")==0)
				strcpy(mime->type,"image/gif");
			else if(stricmp(&mime->shortname[len-4],".iff")==0)
				strcpy(mime->type,"image/x-ilbm");
			else if(stricmp(&mime->shortname[len-4],".wav")==0)
				strcpy(mime->type,"audio/x-wav");
			else if(stricmp(&mime->shortname[len-5],".mpeg")==0)
				strcpy(mime->type,"video/mpeg");
			else if(stricmp(&mime->shortname[len-4],".mpg")==0)
				strcpy(mime->type,"video/mpeg");
			else if(stricmp(&mime->shortname[len-4],".mov")==0)
				strcpy(mime->type,"video/quicktime");
			else if(stricmp(&mime->shortname[len-5],".anim")==0)
				strcpy(mime->type,"video/x-anim");
			/*if(stricmp(&mime->shortname[len-],".")==0)
				strcpy(mime->type,"/";*/
			else if(*mime->type==0) {
				MUI_RequestA(app,0,0,"MIME Attachment","_Okay","NewsCoaster is unable to determine\nthe file format of this attachment.\nPlease set it manually",0);
				strcpy(mime->type,"text/plain");
			}
			okay=TRUE;
		}
		UnLock(lock);
		lock=NULL;
	}
	if(fib)
	{
		FreeDosObject(DOS_FIB,fib);
		fib=NULL;
	}
	return okay;
}

void update_groups() {
	nLog("update_groups() called\n");
	// reads in the available groups
	GroupData * gdata = NULL;
	MessageListData * mdata = NULL;
	BPTR file=NULL;
	BPTR lock=NULL;
	BPTR file2=NULL;
	BPTR lock2=NULL;
	char folder[256]="";
	//char filename2[256]="";
	int maxID,mgID=-1;
	sprintf(folder,"NewsCoasterData:");
	set(wnd_main,MUIA_Window_Sleep,TRUE);
	clearGdata();
	if(account.grouplistType!=0) {
		tn_folders=(MUI_NListtree_TreeNode *)DoMethod(LISTTREE_groupdata,MUIM_NListtree_Insert,"Folders",NULL,MUIV_NListtree_Insert_ListNode_Root,MUIV_NListtree_Insert_PrevNode_Tail,TNF_LIST);
		tn_newsgroups=(MUI_NListtree_TreeNode *)DoMethod(LISTTREE_groupdata,MUIM_NListtree_Insert,"Newsgroups",NULL,MUIV_NListtree_Insert_ListNode_Root,MUIV_NListtree_Insert_PrevNode_Tail,TNF_LIST);
	}
	FileInfoBlock * fib=(FileInfoBlock *)AllocDosObject(DOS_FIB,NULL);
	lock=Lock(folder,ACCESS_READ);
	BOOL okay = FALSE;
	int entries = 0,k = 0;
	if(lock) {
		if(fib) {
			Examine(lock,fib);
			while(ExNext(lock,fib)) {
				okay=FALSE;
				if(strincmp_q(fib->fib_FileName,"FOLDER_",7)==0) {
					gdata=new GroupData();
					gdata->ID = atoi(&fib->fib_FileName[7]);
					if(gdata->ID>mgID)
						mgID=gdata->ID;
					sprintf(gdata->name,"Unknown (%d)",gdata->ID);
					okay=TRUE;
				}
				else if(stricmp(fib->fib_FileName,"outgoing")==0) {
					gdata=new GroupData();
					gdata->ID=-1;
					strcpy(gdata->name,".outgoing");
					okay=TRUE;
				}
				else if(stricmp(fib->fib_FileName,"sent")==0) {
					gdata=new GroupData();
					gdata->ID=-2;
					strcpy(gdata->name,".sent");
					okay=TRUE;
				}
				else if(stricmp(fib->fib_FileName,"deleted")==0) {
					gdata=new GroupData();
					gdata->ID=-3;
					strcpy(gdata->name,".deleted");
					okay=TRUE;
				}
				if(okay) {
					gdata->s=FALSE;
					gdata->defsig=-1;
					DateStamp(&gdata->lastdlds);
					gdata->max_dl=-1;
					if(account.grouplistType==0)
						DoMethod(NLIST_groupdata,MUIM_NList_InsertSingle,gdata,MUIV_NList_Insert_Sorted);
					else {
						if(gdata->ID<0)
							DoMethod(LISTTREE_groupdata,MUIM_NListtree_Insert,"",gdata,tn_folders,MUIV_NListtree_Insert_PrevNode_Tail,TNF_LIST);
						else
							DoMethod(LISTTREE_groupdata,MUIM_NListtree_Insert,"",gdata,tn_newsgroups,MUIV_NListtree_Insert_PrevNode_Tail,TNF_LIST);
					}
					set_and_read(gdata);
					get(NLIST_messagelistdata,MUIA_NList_Entries,&entries);
					maxID=-1;
					for(k=0;k<entries;k++) {
						DoMethod(NLIST_messagelistdata,MUIM_NList_GetEntry,k,&mdata);
						if(mdata->ID>maxID)
							maxID=mdata->ID;
					}
					gdata->nextmID=maxID+1;
					redrawGdataAll();
				}
			}
		}
	}
	nextID=mgID+1;
	resetGdataActive();
	set(wnd_main,MUIA_Window_Sleep,FALSE);
	if(fib) {
		FreeDosObject(DOS_FIB,fib);
		fib=NULL;
	}
	if(lock) {
		UnLock(lock);
		lock=NULL;
	}
	account.save_data();
	return;
}

void get_newsgroups(char *newsgroups,int gID,int mID) {

	char filename[300] = "";
	getFilePath(filename,gID,mID);

	//nLog("get_newsgroups((NewMessage *)%d,(char *)%s,(BOOL)%d,(BOOL)%d) called\n",newmess,filename,getRefs,trimRefs);
	BPTR file=NULL;
	BPTR lock=NULL;
	lock=Lock(filename,ACCESS_READ);
	file=Open(filename,MODE_OLDFILE);
	if(file) {

		char buffer[MAXLINE] = "";

		for(;;) {
			if(!FGets(file,buffer,MAXLINE))
				break;


			if( *buffer=='\0' || *buffer=='\n' || (*buffer=='\r' && buffer[1]=='\n') )
				break;

			if(strincmp_q(buffer,"NEWSGROUPS: ",12)==0) {
				StripNewLine(&buffer[12]);
				strcpy(newsgroups,&buffer[12]);
				break;
			}
		}

		Close(file);
		file=NULL;
	}
	if(lock) {
		UnLock(lock);
		lock=NULL;
	}

}

void get_refs(NewMessage * newmess,BPTR file,getrefs_t getRefs,BOOL trimRefs) {
	// getRefs: 0=no, 1=get all, 2=get last only
	// trimRefs: reduce number of refs if too long?
	int cref = 0;
	char ** ref=newmess->references;
	char word1[1024] = "";
	char word2[1024] = "";
	char isobuf[4096] = "";
	const int BUFLEN = 2 * MAXLINE;
	//char buffer[BUFLEN] = "";
	//char nextline[MAXLINE] = "";
	char *buffer = new char[BUFLEN];
	char *nextline = new char[MAXLINE];
	char *ptr = NULL,*ptr2 = NULL;
	int k = 0,c = 0;

	*newmess->from = '\0';
	//*newmess->replyto = '\0';
	//*newmess->to = '\0';
	*newmess->newsgroups = '\0';
	*newmess->followup = '\0';
	*newmess->subject = '\0';
	*newmess->messageID = '\0';
	*newmess->supersedeID = '\0';
	*newmess->date = '\0';
	*newmess->type = '\0';
	*newmess->xnewsreader = '\0';
	*newmess->dummyHeader = '\0';

	newmess->mIDhash = 0;
	newmess->xno = FALSE;
	newmess->online = FALSE;
	newmess->lines = 0;
	BOOL getNextLine = TRUE;
	BOOL lastHeader = FALSE;
	Seek(file,0,OFFSET_BEGINNING);
		for(;;) {
			int len = 0;
			for(;;) {
				int nlen = 0;
				if(*nextline==0) {
					if(!FGets(file,&buffer[len],BUFLEN - len)) {
						lastHeader = TRUE;
						break;
					}
					StripNewLine(&buffer[len]);
					// get rid of excess whitespace
					//    ..at end
					StripTrail(&buffer[len],' ');
					//    ..at start
					ptr=&buffer[len];
					while(isspace(*ptr))
						ptr++;
					ptr2=&buffer[len];
					//printf("%d (%c) , %d (%c)\n",ptr,ptr,ptr2,ptr2);
					if(ptr!=ptr2) {
						while(*ptr!='\0')
							*ptr2++ = *ptr++;
						*ptr2='\0';
					}
					//printf("*%s*\n",&buffer[len]);
					if(buffer[len]=='\0') {
						lastHeader = TRUE;
						//printf("!%d *%c*\n",buffer[len-1],buffer[len-1]);
						break;
					}
				}
				else {
					strncpy(buffer,nextline,BUFLEN-1);
					buffer[BUFLEN-1] = '\0';
					StripTrail(buffer,' ');
					*nextline=0;
				}
				//printf(">%s<\n",buffer);
				nlen = strlen(buffer);
				buffer[nlen++] = ' '; // newlines should give a space
				buffer[nlen] = '\0';
				BOOL nl = FALSE;
				ptr2 = strchr(&buffer[len],' ');
				if(ptr2[-1]==':' && len>0) { // assume line of next header
					strncpy(nextline,&buffer[len],MAXLINE-1);
					nextline[MAXLINE-1] = '\0';
					buffer[len-1]=0; // end the buffer, also removing the last space
					//printf(">>>%s<<<\n",buffer);
					break;
				}
				len = nlen;
			}
			if(len == 0)
				break;
			if(*buffer == '\0')
				break;
			if(lastHeader) {
				// need to remove the last space (which came from the newline character)
				if(buffer[len-1] == ' ')
					buffer[len-1] = '\0';
			}
			//StripTrail(buffer,' ');
			wordFirstUpper(word1,buffer);
			//printf(":*%s*\n",buffer);
			if(strlen(word1) == strlen(buffer)) {
				// empty header
			}
			else if(strcmp(word1,"FROM:")==0) {
				translateIso(isobuf,&buffer[6]);
				strncpy(newmess->from,isobuf,NEWMESS_long);
				//strncpy(newmess->from,&buffer[6],NEWMESS_long);
				newmess->from[NEWMESS_long]=0;
			}
			/*else if(strcmp(word1,"REPLY-TO:")==0) {
				strncpy(newmess->replyto,&buffer[10],NEWMESS_long);
				newmess->replyto[NEWMESS_long]=0;
			}*/
			/*else if(strcmp(word1,"TO:")==0) {
				strncpy(newmess->to,&buffer[4],NEWMESS_long);
				newmess->to[NEWMESS_long]=0;
			}*/
			else if(strcmp(word1,"NEWSGROUPS:")==0) {
				strncpy(newmess->newsgroups,&buffer[12],NEWMESS_long);
				newmess->newsgroups[NEWMESS_long]=0;
			}
			else if(strcmp(word1,"FOLLOWUP-TO:")==0) {
				strncpy(newmess->followup,&buffer[13],NEWMESS_long);
				newmess->followup[NEWMESS_long]=0;
			}
			else if(strcmp(word1,"SUBJECT:")==0) {
				translateIso(isobuf,&buffer[9]);
				strncpy(newmess->subject,isobuf,NEWMESS_long);
				//strncpy(newmess->subject,&buffer[9],NEWMESS_long);
				newmess->subject[NEWMESS_long]=0;
			}
			else if(strcmp(word1,"MESSAGE-ID:")==0) {
				strncpy(newmess->messageID,&buffer[12],NEWMESS_short);
				newmess->messageID[NEWMESS_short]=0;
				//newmess->mIDhash = calculate_mID_hash(newmess->messageID);
			}
			else if(stricmp(buffer,"X-NO-ARCHIVE: YES")==0)
				newmess->xno=TRUE;
			else if(strcmp(word1,"DATE:")==0) {
				strncpy(newmess->date,&buffer[6],NEWMESS_shortshort);
				newmess->date[NEWMESS_shortshort]=0;
			}
			else if(strcmp(word1,"CONTENT-TYPE:")==0) {
				strncpy(newmess->type,&buffer[14],63);
				newmess->type[63]=0;
				StripChar(newmess->type,';');
			}
			else if(strcmp(word1,"X-NEWSREADER:")==0) {
				strncpy(newmess->xnewsreader,&buffer[14],NEWMESS_long);
				newmess->xnewsreader[NEWMESS_long] = '\0';
			}
			else if(strncmp(buffer,onlineflag,strlen(buffer))==0) {
				//printf("!!!\n");
				newmess->online=TRUE;
			}
			else if(strcmp(word1,"LINES:")==0)
				newmess->lines = atoi(&buffer[7]);
			else if(getRefs!=GETREFS_NONE && strcmp(word1,"REFERENCES:")==0) {
				getNextLine=FALSE;
				if(getRefs==GETREFS_ALL) {
					c = 1;
					do {
						word(word2,&buffer[12],c++,'>');
						char *wptr = word2;
						while(*wptr != NULL && isspace(*wptr))
							wptr++;
						if(*wptr != NULL) {
							int wlen = strlen(wptr);
							char *w = new char[ wlen + 2 ];
							strncpy(w,wptr,wlen);
							w[wlen] = '>';
							w[wlen+1] = '\0';
							ref[cref++] = w;
							if(cref==MAX_REFS) {
								nLog("Error - hit MAX_REFS limit of %d\n",cref);
								break;
							}
						}
					} while(*word2 != NULL);
				}
				else if(getRefs==GETREFS_LAST) {
					char *lastref = NULL;
					char *ptr = buffer;
					for(;;) {
						ptr = strchr(ptr,'<');
						if(ptr == NULL)
							break;
						lastref = ptr;
						ptr++;
					}
					if(lastref != NULL) {
						char *end = strchr(lastref,'>');
						if(end != NULL) {
							int wlen = (int)end - (int)lastref + 1;
							char *w = new char[wlen+1];
							strncpy(w,lastref,wlen);
							w[wlen] = '\0';
							ref[cref++] = w;
						}
					}
				}
			}
			if(*newmess->getThisHeader!=0) {
				if(stricmp(word1,newmess->getThisHeader)==0) {
					strncpy(newmess->dummyHeader,&buffer[strlen(newmess->getThisHeader)+1],NEWMESS_long);
					newmess->dummyHeader[NEWMESS_long] = '\0';
				}
			}
			if(lastHeader)
				break;
		}

	int tlen=12;
	if(getRefs==GETREFS_ALL && cref>0 && trimRefs==TRUE) {
		for(k=0;k<cref;k++) {
			tlen += strlen(ref[k]);
			tlen++;
		}
		if(tlen>996 && cref > 5) {
			// line too long! lose some references!
			if(ref[4] != NULL && ref[cref-1] != NULL) {
				delete [] ref[4];
				int len = strlen( ref[cref-1] );
				ref[4] = new char[len + 1];
				strcpy(ref[4],ref[cref-1]);
				delete [] ref[cref-1];
			}
			for(k=5;k<cref;k++) {
				if(ref[k])
					ref[k]=NULL;
			}
			cref = 5;
		}
	}
	newmess->nrefs = cref;
	delete [] buffer;
	delete [] nextline;
}

void get_refs(NewMessage * newmess,char *filename,getrefs_t getRefs,BOOL trimRefs) {
	nLog("get_refs((NewMessage *)%d,(char *)%s,(BOOL)%d,(BOOL)%d) called\n",newmess,filename,getRefs,trimRefs);
	BPTR file=NULL;
	BPTR lock=NULL;
	lock=Lock(filename,ACCESS_READ);
	file=Open(filename,MODE_OLDFILE);
	if(file) {
		get_refs(newmess,file,getRefs,trimRefs);
		Close(file);
		file=NULL;
	}
	if(lock) {
		UnLock(lock);
		lock=NULL;
	}
}

void get_refs(NewMessage * newmess,int gID,int mID,getrefs_t getRefs) {
	char filename[300] = "";
	getFilePath(filename,gID,mID);
	get_refs(newmess,filename,getRefs,TRUE);
}

void get_refs(NewMessage * newmess,GroupData * gdata,MessageListData * mdata,getrefs_t getRefs) {
	get_refs(newmess,gdata->ID,mdata->ID,getRefs);
}

BOOL search_mess(GroupData * gdata,MessageListData * mdata,char * text,BOOL casesens,int section) {
	// section: 1=header, 2=body, 3=all
	// if casesens==TRUE, text must be in upper case!
	if(*text==0)
		return FALSE;
	BOOL found=FALSE;
	BPTR file=NULL;
	BPTR lock=NULL;
	char filename[300] = "";
	getFilePath(filename,gdata->ID,mdata->ID);
	lock=Lock(filename,ACCESS_READ);
	file=Open(filename,MODE_OLDFILE);
	char buffer[MAXLINE] = "";
	BOOL header=TRUE;
	if(file)
	{
		// do header first - slow bit
		for(;;)	{
			if(!FGets(file,buffer,MAXLINE))
				break;
			StripNewLine(buffer);
			if(*buffer==0) {
				header=FALSE;
				if(section==SEARCH_HEADER) // only searching the header?
					break;
			}
			//if( (header==TRUE && (section & 1)!=0) || (header==FALSE && (section & 2)!=0) ) {
			if( (header==TRUE && section != SEARCH_BODY) || (header==FALSE && section != SEARCH_HEADER) ) {
				if(casesens) {
					if(strstr(buffer,text)!=NULL) {
						found=TRUE;
						break;
					}
				}
				else {
					if(stristr_q(buffer,text)!=NULL) {
						found=TRUE;
						break;
					}
				}
			}	
		}
		Close(file);
		file=NULL;
	}
	if(lock)
	{
		UnLock(lock);
		lock=NULL;
	}
	return found;
}

BOOL readInText(Object * textEditor,char *filename) {
	nLog("readInText((Object *)%d,(char *)%s) called\n",textEditor,filename);
	BPTR file=NULL;
	BPTR lock=NULL;
	lock=Lock(filename,ACCESS_READ);
	file=Open(filename,MODE_OLDFILE);
	char buffer[MAXLINE+1] = "";
	int length = 0;
	if(file) {
		set(textEditor,MUIA_TextEditor_Quiet,TRUE);
		do {
			length=Read(file,buffer,MAXLINE);
			if(length<=0)
				break;
			buffer[length]=0;
			DoMethod(textEditor,MUIM_TextEditor_InsertText,buffer,MUIV_TextEditor_InsertText_Bottom);
		} while(1);
		Close(file);
		set(textEditor,MUIA_TextEditor_Quiet,FALSE);
	}
	if(lock) {
		UnLock(lock);
		lock=NULL;
	}
	return (file!=NULL);
}

BOOL update_index() {
	nLog("update_index() called\n");
	// updates the index of the current folder
	GroupData * gdata = NULL;
	MessageListData * mdata = NULL;
	getGdataActive(&gdata);
	if(gdata==NULL)
		return FALSE;
	c_gdata=gdata;
	BPTR file=NULL;
	BPTR lock=NULL;
	BPTR file2=NULL;
	BPTR lock2=NULL;
	char buffer[1024]="";
	char folder[256]="";
	char filename[300]="";
	int maxID=-1;
	if(gdata->ID==-1)
		sprintf(folder,"NewsCoasterData:outgoing/");
	else if(gdata->ID==-2)
		sprintf(folder,"NewsCoasterData:sent/");
	else if(gdata->ID==-3)
		sprintf(folder,"NewsCoasterData:deleted/");
	else if(gdata->ID>=0)
		sprintf(folder,"NewsCoasterData:folder_%d/",gdata->ID);
	setMdataQuiet(TRUE);
	set(wnd_main,MUIA_Window_Sleep,TRUE);
	clearThreadView();
	DoMethod(NLIST_messagelistdata,MUIM_NList_Clear);
	const int mm=100;
	FileInfoBlock * fib=(FileInfoBlock *)AllocDosObject(DOS_FIB,NULL);
	lock=Lock(folder,ACCESS_READ);
	int nummess=0;
	BOOL aborted = FALSE;
	if(lock) {
		if(fib) {
			StatusWindow * statusWindow = new StatusWindow(app,"Scanning..");
			sprintf(buffer,"Scanning: %s (found: ",gdata->name);
			char *swptr = &buffer[ strlen(buffer) ];
			sprintf(swptr,"0 )",nummess);
			statusWindow->setText(buffer);
			Examine(lock,fib);
			while(ExNext(lock,fib)) {
				DoMethod(app,MUIM_Application_InputBuffered);
				if(nummess % 64 == 0) {
					do_input();
					if(statusWindow->isAborted()==TRUE || running==FALSE) {
						aborted = TRUE;
						break;
					}
					sprintf(swptr,"%d)",nummess);
					statusWindow->setText(buffer);
				}
				if(strncmp(fib->fib_FileName,"news_",5)==0) {
					//news item found
					nLog("  found news file: %s\n",fib->fib_FileName);
					mdata=new MessageListData();
					if(mdata != NULL) {
						nLog("   mdata: %d\n",mdata);
					
						mdata->ID = atoi(&fib->fib_FileName[5]);
						if(mdata->ID>maxID)
							maxID=mdata->ID;
						{
							NewMessage newmess;
							//get_refs(&newmess,gdata,mdata,GETREFS_ALL);
							get_refs(&newmess,gdata,mdata,GETREFS_LAST);
							newmess.copyToMessageListData(mdata);
						}
						getFilePath(filename,gdata->ID,mdata->ID);
						lock2=Lock(filename,ACCESS_READ);
						if(lock2) {
							FileInfoBlock * fib2=(FileInfoBlock *)AllocDosObject(DOS_FIB,NULL);
							if(Examine(lock2,fib2))
								mdata->size=fib2->fib_Size;
							if(fib2) {
								FreeDosObject(DOS_FIB,fib2);
								fib2=NULL;
							}
						}
						if(lock2) {
							UnLock(lock2);
							lock2=NULL;
						}
						/*if(*mdata->type==0)
							strcpy(mdata->type,"text/plain");*/
						DoMethod(NLIST_messagelistdata,MUIM_NList_InsertSingle,mdata,MUIV_NList_Insert_Sorted);
						nummess++;
					}
					else {
						nLog("  Not enough RAM to allocate MessageListData struct! Aborting..\n");
						MUI_RequestA(app,0,0,"Severe Error!","_Okay","Not enough RAM!",0);
						aborted = TRUE;
						break;
					}
				}
			}
			nLog(" finished scanning\n");
			if(aborted)
				read_index();
			else {
				gdata->nummess=nummess;
				gdata->num_unread = 0;
				redrawGdataAll();
				gdata->nextmID=maxID+1;
			}
			threadView();
			if(!aborted)
				write_index(0);
			delete statusWindow;
		}
	}
	set(wnd_main,MUIA_Window_Sleep,FALSE);
	setMdataQuiet(FALSE);
	if(nummess>0)
		setMdataActive(0);
	if(fib) {
		FreeDosObject(DOS_FIB,fib);
		fib=NULL;
	}
	if(lock) {
		UnLock(lock);
		lock=NULL;
	}
	setEnabled();
	nLog("  update_index() finished\n");
	return aborted;
}

void import_file(char *filename2) {
	nLog("import_file((char *)%s) called\n",filename2);
	GroupData * gdata = NULL;
	MessageListData * mdata = NULL;
	BPTR file2=NULL;
	BPTR lock2=NULL;
	char filename[256]="";
	char command[256]="";
	int maxID=-1;
					lock2=Lock(filename2,ACCESS_READ);
					file2=Open(filename2,MODE_OLDFILE);
					if(file2)
					{
						//file found
						//ctypegot=FALSE;
						mdata=new MessageListData();
						gdata=NULL;
						FileInfoBlock * fib2=(FileInfoBlock *)AllocDosObject(DOS_FIB,NULL);
						if(lock2)
						{
							if(Examine(lock2,fib2))
								mdata->size=fib2->fib_Size;
						}
						if(fib2)
						{
							FreeDosObject(DOS_FIB,fib2);
							fib2=NULL;
						}
						
						{
							NewMessage * newmess = new NewMessage;
							get_refs(newmess,filename2,GETREFS_LAST,FALSE);
							//get_refs(newmess,filename2,GETREFS_ALL,FALSE);
							newmess->copyToMessageListData(mdata);
						}
						
						if(*mdata->newsgroups!=0)
						{
							get_gdata(&gdata,mdata->newsgroups); // cross posts only go into one folder atm!
							if(gdata)
							{
								mdata->ID=gdata->nextmID;
								gdata->nextmID++;
								mdata->flags[6]=gdata->ID;
							}
						}
						Close(file2);
						file2=NULL;
						{
							if(gdata)
							{
								// looks like a valid news item; successfully extracted newsgroup header
								sprintf(filename,"folder_%d/news_%d",gdata->ID,mdata->ID);
								sprintf(command,"Copy NewsCoasterData:%s to NewsCoasterData:%s",filename2,filename);
								Execute(command,NULL,NULL);
								write_index_single(gdata,mdata);
							}
						}
						//delete mdata;
					}
					if(lock2)
					{
						UnLock(lock2);
						lock2=NULL;
					}
}

void import_folder(char * ifolder,StatusWindow * statusWindow) {
	nLog("import_folder((char *)%s) called\n",ifolder);
	// imports messages from another directory
	char folder[1024] = "";
	char subfolder[1024]="";
	char filename[1024] = "";
	char info[256]="";
	sprintf(info,"Scanning... %s\n",ifolder);
	statusWindow->setText(info);
	GroupData * gdata=NULL;
	BPTR file=NULL;
	BPTR lock=NULL;
	BPTR file2=NULL;
	BPTR lock2=NULL;
	int maxID=-1;
	if(stristr(ifolder,":")==NULL)
		sprintf(folder,"NewsCoaster:%s",ifolder);
	else
		strcpy(folder,ifolder);
	const int mm=100;
	FileInfoBlock * fib=(FileInfoBlock *)AllocDosObject(DOS_FIB,NULL);
	lock=Lock(folder,ACCESS_READ);
	if(lock) {
		if(fib) {
			Examine(lock,fib);
			set(wnd_main,MUIA_Window_Sleep,TRUE);
			while(ExNext(lock,fib)) {
				if(fib->fib_DirEntryType>0) {
					//sub-directory
					sprintf(subfolder,"%s%s/",folder,fib->fib_FileName);
					import_folder(subfolder,statusWindow);
				}
				else {
					sprintf(filename,"%s%s",folder,fib->fib_FileName);
					import_file(filename);
					
				}
				//DoMethod(app,MUIM_Application_InputBuffered);
				do_input(); // input loop
				if(statusWindow->isAborted()==TRUE || running==FALSE)
					break;
			}
			setEnabled();
			set(wnd_main,MUIA_Window_Sleep,FALSE);
		}
	}
	if(fib) {
		FreeDosObject(DOS_FIB,fib);
		fib=NULL;
	}
	if(lock) {
		UnLock(lock);
		lock=NULL;
	}
	return;
}

void import()
{
	nLog("import() called\n");
	char folder[1024]="";
	sleepAll(TRUE);
	if(!LoadASL(folder,"Directory to Scan...","","#?",TRUE)) {
		sleepAll(FALSE);
		return;
	}
	StatusWindow * statusWindow = new StatusWindow(app,"Scanning..");
	import_folder(folder,statusWindow);
	delete statusWindow;
	sleepAll(FALSE);
	read_index();
}

void save_killfile(char *filename) {
	nLog("save_killfile((char *)%s) called\n",filename);
	//save folder prefs
	char filenamenew[256] = "";
	sprintf(filenamenew,"%s.new",filename);
	DeleteFile(filenamenew);
	int entries = 0;
	get(NLIST_acc_KILLFILE,MUIA_NList_Entries,&entries);
	//Write info...
	BPTR file = Open(filenamenew,MODE_NEWFILE);
	if(file) {
		for(int k=0;k<entries;k++) {
			KillFile * kill = NULL;
			DoMethod(NLIST_acc_KILLFILE,MUIM_NList_GetEntry,k,&kill);
			Write(file,kill,sizeof(KillFile));
		}
		Close(file);
		file=NULL;
	}
	DeleteFile(filename);
	Rename(filenamenew,filename);
}

void save_killfile() {
	char filename[] = "NewsCoasterData:.killfile";
	save_killfile(filename);
}

void load_killfile() {
	nLog("load_killfile() called\n");
	KillFile * kill = NULL;
	BPTR file=NULL;
	BPTR lock=NULL;
	int temp = 0;
	//char filename[MAXFILENAME]="";
	//save folder prefs
	char filename[] = "NewsCoasterData:.killfile";
	lock=Lock(filename,ACCESS_READ);
	//Write info...
	file=Open(filename,MODE_OLDFILE);
	BOOL expired;
	struct DateStamp ds;
	DateStamp(&ds);
	if(file)
	{
		DoMethod(NLIST_acc_KILLFILE,MUIM_NList_Clear);
		do
		{
			kill=new KillFile();
			temp=Read(file,kill,sizeof(KillFile));
			if(temp<=0)
				break;
			nLog("  Read killfile: %s %s %s\n",kill->header,kill->text,kill->ngroups);
			// has killfile expired?
			expired=FALSE;
			if(kill->expiretype==1) // days since creation
			{
				if(ds.ds_Days - kill->ds.ds_Days > kill->expire)
					expired=TRUE;
			}
			else if(kill->expiretype==2) // days since last used
			{
				if(ds.ds_Days - kill->lastused.ds_Days > kill->expire)
					expired=TRUE;
			}
			if(!expired) {
				// convert to upper case
				toUpper(kill->header);
				toUpper(kill->text);
				toUpper(kill->ngroups);
				DoMethod(NLIST_acc_KILLFILE,MUIM_NList_InsertSingle,kill,MUIV_NList_Insert_Bottom);
			}
			else
			{
				delete kill;
				kill=NULL;
			}
		} while(1);
		if(kill)
		{
			delete kill;
			kill=NULL;
		}
		Close(file);
		file=NULL;
	}
	if(lock)
	{
		UnLock(lock);
		lock=NULL;
	}
}

Server * getDefaultServer() {
	Server *server=NULL;
	int entries = 0;
	get(NLIST_acc_SERVERS,MUIA_NList_Entries,&entries);
	for(int i=0;i<entries;i++) {
		DoMethod(NLIST_acc_SERVERS,MUIM_NList_GetEntry,i,&server);
		if(server->def==TRUE)
			return server;
		if(i==entries-1) // no default server! make last one the default
			server->def=TRUE;
	}
	return NULL;
}

Server * getPostingServer() {
	Server *server=NULL;
	int entries = 0;
	get(NLIST_acc_SERVERS,MUIA_NList_Entries,&entries);
	for(int i=0;i<entries;i++) {
		DoMethod(NLIST_acc_SERVERS,MUIM_NList_GetEntry,i,&server);
		if(server->post==TRUE)
			return server;
		if(i==entries-1) // no posting server! use default
			return getDefaultServer();
	}
	return NULL;
}

/*Server * getServerPosting() {
	if(*account.nntppost!=0) {
	}
}*/

Server * getServer(int ID) {
	if(ID==0)
		return getDefaultServer();
	Server *server=NULL;
	int entries = 0;
	get(NLIST_acc_SERVERS,MUIA_NList_Entries,&entries);
	for(int i=0;i<entries;i++) {
		DoMethod(NLIST_acc_SERVERS,MUIM_NList_GetEntry,i,&server);
		if(server->ID==ID)
			return server;
	}
	// not found! return default server instead
	return getDefaultServer();
}

Server * getPostingServerForGroup(char *group) {
	Server *server = NULL;
	GroupData *gdata = NULL;
	get_gdata(&gdata,group);
	
	if( gdata == NULL
		|| gdata->serverID == 0
		|| !gdata->moreflags[4]
		)
		server = getPostingServer(); // default
	else {
		// we're posting with a non default server
		server = getServer(gdata->serverID);
	}
	
	return server;
}

void freeServerCycle() {
	if(GROUP_ngadv_SUB != NULL) {
		DoMethod(GROUP_ngadv,OM_REMMEMBER,GROUP_ngadv_SUB);
		MUI_DisposeObject(GROUP_ngadv_SUB);
		GROUP_ngadv_SUB = NULL;
	}
	for(int i=0;;) {
		if(CYA_ngadv_server[i] == NULL)
			break;
		delete [] CYA_ngadv_server[i++];
	}
	delete [] CYA_ngadv_server;
	delete [] server_list;
}

int setServerCycle(int ID) {
	Server *server = NULL;
	int entries = 0;
	get(NLIST_acc_SERVERS,MUIA_NList_Entries,&entries);
	CYA_ngadv_server = new char *[entries+1];
	server_list = new int[entries];

	int active=0;
	for(int i=0;i<entries;i++) {
		DoMethod(NLIST_acc_SERVERS,MUIM_NList_GetEntry,i,&server);
		CYA_ngadv_server[i] = new char[SERVER_LEN+1];
		strncpy(CYA_ngadv_server[i],server->nntp,SERVER_LEN);
		(CYA_ngadv_server[i])[SERVER_LEN] = '\0';
		server_list[i] = server->ID;
		if(server->ID == ID)
			active = i;
	}
	CYA_ngadv_server[entries] = NULL;
	GROUP_ngadv_SUB = VGroup,
		Child, HGroup,
			Child, Label2("Newsserver:"),
			Child, CY_ngadv_SERVER = Cycle(CYA_ngadv_server),
			Child, Label1("Default?:"),
			Child, CM_ngadv_SERVER = CheckMark(FALSE),
			End,
		Child, HGroup,
			Child, HSpace(0),
			Child, Label1("Post with this server?:"),
			Child, CM_ngadv_SERVERPOST = CheckMark(FALSE),
			End,
		//Child, STR_ngadv_SERVER=BetterStringObject, StringFrame, MUIA_String_Contents, "", MUIA_String_MaxLen, 64, MUIA_CycleChain, 1, End,
		End;
	DoMethod(GROUP_ngadv,OM_ADDMEMBER,GROUP_ngadv_SUB);
	//set(CY_ngadv_SERVER,MUIA_Cycle_Entries,CYA_ngadv_server);

	DoMethod(CM_ngadv_SERVER,MUIM_Notify,MUIA_Selected,TRUE,
		CY_ngadv_SERVER,3,MUIM_Set,MUIA_Disabled,TRUE);
	DoMethod(CM_ngadv_SERVER,MUIM_Notify,MUIA_Selected,FALSE,
		CY_ngadv_SERVER,3,MUIM_Set,MUIA_Disabled,FALSE);

	DoMethod(CM_ngadv_SERVER,MUIM_Notify,MUIA_Selected,TRUE,
		CM_ngadv_SERVERPOST,3,MUIM_Set,MUIA_Disabled,TRUE);
	DoMethod(CM_ngadv_SERVER,MUIM_Notify,MUIA_Selected,FALSE,
		CM_ngadv_SERVERPOST,3,MUIM_Set,MUIA_Disabled,FALSE);

	if(ID==0)
		set(CM_ngadv_SERVER,MUIA_Selected,TRUE);
	else
		set(CM_ngadv_SERVER,MUIA_Selected,FALSE);
	set(CY_ngadv_SERVER,MUIA_Cycle_Active,active);
	return active;
}

void save_servers(char *filename) {
	nLog("save_servers((char *)%s) called\n",filename);
	Server * server = NULL;
	BPTR file=NULL;
	//save folder prefs
	DeleteFile(filename);
	int entries = 0;
	get(NLIST_acc_SERVERS,MUIA_NList_Entries,&entries);
	//Write info...
	file=Open(filename,MODE_NEWFILE);
	if(file)
	{
		if(entries>0)
		{
			Write(file,&entries,sizeof(int));
			for(int k=0;k<entries;k++)
			{
				DoMethod(NLIST_acc_SERVERS,MUIM_NList_GetEntry,k,&server);
				Write(file,server,sizeof(Server));
			}
		}
		Close(file);
		file=NULL;
	}
}

void save_servers() {
	char filename[] = "NewsCoasterData:.servers";
	save_servers(filename);
}

void load_servers() {
	nLog("load_servers() called\n");
	Server * server = NULL;
	BPTR file=NULL;
	BPTR lock=NULL;
	int temp = 0;
	char filename[] = "NewsCoasterData:.servers";
	lock=Lock(filename,ACCESS_READ);
	//Write info...
	file=Open(filename,MODE_OLDFILE);
	if(file) {
		DoMethod(NLIST_acc_SERVERS,MUIM_NList_Clear);
		int entries;
		Read(file,&entries,sizeof(int));
		do {
			server=new Server;
			temp=Read(file,server,sizeof(Server));
			if(temp<=0)
				break;
			DoMethod(NLIST_acc_SERVERS,MUIM_NList_InsertSingle,server,MUIV_NList_Insert_Bottom);
			if(server->ID >= nextServerID)
				nextServerID = server->ID + 1;
		} while(1);
		if(server)
		{
			delete server;
			server=NULL;
		}
		Close(file);
		file=NULL;
	}
	if(lock)
	{
		UnLock(lock);
		lock=NULL;
	}
}

void getFolderPath(char *buffer,int gID) {
	nLog("getFolderPath((char *)%d,(int)%d) called\n",buffer,gID);
	if(gID==-1)
		strcpy(buffer,"NewsCoasterData:outgoing");
	else if(gID==-2)
		strcpy(buffer,"NewsCoasterData:sent");
	else if(gID==-3)
		strcpy(buffer,"NewsCoasterData:deleted");
	else
		sprintf(buffer,"NewsCoasterData:folder_%d",gID);
}

void getIndexPath(char *buffer,int gID) {
	nLog("getIndexPath((char *)%d,(int)%d) called\n",buffer,gID);
	if(gID==-1)
		strcpy(buffer,"NewsCoasterData:outgoing/.index");
	else if(gID==-2)
		strcpy(buffer,"NewsCoasterData:sent/.index");
	else if(gID==-3)
		strcpy(buffer,"NewsCoasterData:deleted/.index");
	else
		sprintf(buffer,"NewsCoasterData:folder_%d/.index",gID);
}

void getFilePath(char *buffer,int gID,int mID) {
	nLog("getFilePath((char *)%d,(int)%d,(int)%d) called\n",buffer,gID,mID);
	if(gID==-1)
		sprintf(buffer,"NewsCoasterData:outgoing/news_%d",mID);
	else if(gID==-2)
		sprintf(buffer,"NewsCoasterData:sent/news_%d",mID);
	else if(gID==-3)
		sprintf(buffer,"NewsCoasterData:deleted/news_%d",mID);
	else
		sprintf(buffer,"NewsCoasterData:folder_%d/news_%d",gID,mID);
}

void makeFolder(int gID) {
	nLog("makeFolder((int)%d) called\n",gID);
	char buffer[1024] = "";
	char command[1024] = "";
	BPTR lock = NULL;
	getFolderPath(buffer,gID);
	if(!exists(buffer)) {
		lock=CreateDir(buffer);
		if(lock) {
			UnLock(lock);
			lock=NULL;
		}
	}
	getIndexPath(buffer,gID);
	if(!exists(buffer)) {
		/*sprintf(command,"copy NewsCoaster:default.index %s",buffer);
		Execute(command,NULL,NULL);*/
		writeEmptyIndex(gID);
	}
}

void createOutgoing() {
	nLog("createOutgoing() called\n");
	GroupData * gdata=new GroupData();
	gdata->ID=-1;
	strcpy(gdata->name,".Outgoing");
	gdata->nummess=0;
	gdata->num_unread=0;
	gdata->nextmID=0;
	gdata->s=FALSE;
	gdata->max_dl=-1;
	insertGdata(gdata,TRUE);
	makeFolder(gdata->ID);
}

void createSent() {
	nLog("createSent() called\n");
	GroupData * gdata=new GroupData();
	gdata->ID=-2;
	strcpy(gdata->name,".Sent");
	gdata->nummess=0;
	gdata->num_unread=0;
	gdata->nextmID=0;
	gdata->s=FALSE;
	gdata->max_dl=-1;
	insertGdata(gdata,TRUE);
	makeFolder(gdata->ID);
}

void createDeleted() {
	nLog("createDeleted() called\n");
	GroupData * gdata=new GroupData();
	gdata->ID=-3;
	strcpy(gdata->name,".Deleted");
	gdata->nummess=0;
	gdata->num_unread=0;
	gdata->nextmID=0;
	gdata->s=FALSE;
	gdata->max_dl=-1;
	insertGdata(gdata,TRUE);
	makeFolder(gdata->ID);
}

BOOL exists(char *filename) {
	nLog("exists((char *)%s) called\n",filename);
	BOOL res = FALSE;
	/*BPTR lockout;
	SetIoErr(0L);
	lockout=Lock(filename,SHARED_LOCK);
	if(lockout==NULL) {
		// what type of error?
		LONG err = IoErr();
		if(err==ERROR_OBJECT_IN_USE)
			res = TRUE; // it exists
		// else it doesn't exist
	}
	else {
		UnLock(lockout);
		lockout=NULL;
		res = TRUE
	}*/
	BPTR lock = Lock(filename,ACCESS_READ);
	if(lock != NULL) {
		res = TRUE;
		UnLock(lock);
	}
	nLog("  finished exists() - returning %d\n",res);
	return res;
}

void resetMessageListFormat() {
	nLog("resetMessageListFormat() called\n");
	char *ptr = messagelistformat;
	int cur_flag = 2;
	BOOL first = TRUE;
	for(int i=0;i<6;i++) {
		if((account.listflags & cur_flag) != 0) {
			if(first)
				first = FALSE;
			else
				*ptr++ = ',';
		}
		cur_flag *= 2;
	}
	*ptr = '\0';
	nLog("%s\n",messagelistformat);
	set(NLIST_messagelistdata,MUIA_NList_Format,messagelistformat);
	set(LISTTREE_messagelistdata,MUIA_NListtree_Format,messagelistformat);
}

int getInternalColumn(int col) {
	nLog("getInternalColumn((int)%d) called\n",col);
	//return col;
	int cur_flag = 2;
	for(int i=0;i<6;i++) {
		BOOL col_showed = (account.listflags & cur_flag) != 0;
		//col_showed = TRUE;
		if(col_showed)
			col--;
		if(col < 0) {
			nLog("  returning %d\n",i);
			return i;
		}
		cur_flag *= 2;
	}
	nLog("  UNKNOWN COLUMN!!! returning 0..\n");
	return 0;
}

BOOL getSortType(int *type,int icol,int gID) {
	nLog("getSortType(int *)%d,(int)%d,(int)&d) called\n",type,icol,gID);
	//sorttype: 0=subject, 1=date, 2=from, -1=newsgroups, 3=size, 4=lines
	BOOL res = TRUE;
	*type = 0;
	switch(icol) {
	case 1:
		*type = 0;
		break;
	case 2:
		*type = 1;
		break;
	case 3:
		if(gID < 0)
			*type = -1;
		else
			*type = 2;
		break;
	case 4:
		*type = 3;
		break;
	case 5:
		*type = 4;
		break;
	default:
		res = FALSE;
		break;
	}
	nLog("  setting type to %d\n",*type);
	nLog("  returning %d\n",res);
	return res;
}

BOOL addUser(User * user) {
	char usersfile[] = "NewsCoaster:.users";
	BOOL success=FALSE;
	if(exists(usersfile)) {
		BPTR file = Open(usersfile,MODE_READWRITE);
		if(file != NULL) {
			short nousers = 0,logonreq = 0;
			Read(file,&nousers,sizeof(short));
			nousers++;
			logonreq=TRUE; // now there is more than one user
			Seek(file,0,OFFSET_BEGINNING);
			Write(file,&nousers,sizeof(short));
			Write(file,&logonreq,sizeof(short));
			Seek(file,0,OFFSET_END);
			Write(file,user,sizeof(User));
			success=TRUE;
			Close(file);
			file=NULL;
		}
	}
	else {
		BPTR file = Open(usersfile,MODE_NEWFILE);
		if(file != NULL) {
			short nousers = 0,logonreq = 0;
			nousers=1;
			if(user->requiresPassword())
				logonreq=TRUE;
			else
				logonreq=FALSE;
			Write(file,&nousers,sizeof(short));
			Write(file,&logonreq,sizeof(short));
			short dummy=0;
			for(int i=0;i<16;i++) // spare
				Write(file,&dummy,sizeof(short));
			Write(file,user,sizeof(User));
			success=TRUE;
			Close(file);
			file=NULL;
		}
	}
	return success;
}

BOOL replaceUser(User * user) {
	char usersfile[] = "NewsCoaster:.users";
	BOOL success=FALSE;
	if(exists(usersfile)) {
		BPTR file = Open(usersfile,MODE_READWRITE);
		if(file != NULL) {
			short nousers = 0,logonreq = 0;
			Read(file,&nousers,sizeof(short));
			Read(file,&logonreq,sizeof(short));
			Seek(file,-sizeof(short),OFFSET_CURRENT);
			if(nousers==1 && user->requiresPassword()==TRUE && logonreq==FALSE)
				logonreq=TRUE;
			else if(nousers==1 && user->requiresPassword()==FALSE && logonreq==TRUE)
				logonreq=FALSE;
			Write(file,&logonreq,sizeof(short));
			Seek(file,18*sizeof(short),OFFSET_BEGINNING);
			for(int i=0;i<nousers;i++) {
				User user2;
				Read(file,&user2,sizeof(User));
				if(strcmp(user->getName(),user2.getName())==0) {
					Seek(file,-sizeof(User),OFFSET_CURRENT);
					Write(file,user,sizeof(User));
					success=TRUE;
					break;
				}
			}
			Close(file);
			file=NULL;
		}
	}
	return success;
}

void saveUsers() {
	nLog("saveUsers() called\n");
	int k = 0;
	User * user = NULL;
	//char filename[MAXFILENAME] = "";
	// save folder prefs
	char filename[] = "NewsCoaster:.users";
	DeleteFile(filename);
	int entries = 0;
	get(NLIST_users_LIST,MUIA_NList_Entries,&entries);
	// Write info...
	BPTR file = Open(filename,MODE_NEWFILE);
	if(file != NULL) {
		short nousers=entries,logonreq=TRUE;
		if(entries==1) {
			DoMethod(NLIST_users_LIST,MUIM_NList_GetEntry,k,&user);
			if(user->requiresPassword()==FALSE)
				logonreq=FALSE;
		}
		Write(file,&nousers,sizeof(short));
		Write(file,&logonreq,sizeof(short));
		short dummy=0;
		for(int i=0;i<16;i++) // spare
			Write(file,&dummy,sizeof(short));
		for(k=0;k<entries;k++) {
			DoMethod(NLIST_users_LIST,MUIM_NList_GetEntry,k,&user);
			Write(file,user,sizeof(User));
		}
		Close(file);
		file=NULL;
	}
}

int checkUniqueUser(char * name,char * dataLoc) {
	User * user = NULL;
	int entries = 0;
	get(NLIST_users_LIST,MUIA_NList_Entries,&entries);
	for(int k=0;k<entries;k++) {
		DoMethod(NLIST_users_LIST,MUIM_NList_GetEntry,k,&user);
		if(strcmp(user->getName(),name)==0)
			return 1;
		else if(stricmp(user->dataLocation,dataLoc)==0)
			return 2;
	}
	return 0;
}

void loadUsers() {
	nLog("loadUsers() called\n");
	User * user = NULL;
	int temp = 0;
	char filename[] = "NewsCoaster:.users";
	BPTR lock = Lock(filename,ACCESS_READ);
	BPTR file = Open(filename,MODE_OLDFILE);
	if(file != NULL) {
		Seek(file,18*sizeof(short),OFFSET_CURRENT); // spare
		DoMethod(NLIST_users_LIST,MUIM_NList_Clear);
		do {
			user = new User;
			temp=Read(file,user,sizeof(User));
			if(temp<=0)
				break;
			DoMethod(NLIST_users_LIST,MUIM_NList_InsertSingle,user,MUIV_NList_Insert_Bottom);
		} while(1);
		if(user) {
			delete user;
			user=NULL;
		}
		Close(file);
		file=NULL;
	}
	if(lock) {
		UnLock(lock);
		lock=NULL;
	}
}

void readInGroups() {
	nLog("readInGroups() called\n");
	GroupData * gdata = NULL;
	char filename[] = "NewsCoasterData:.prefs";
	BPTR lock = Lock(filename,ACCESS_READ);
	//Read info...
	BPTR file=Open(filename,MODE_OLDFILE);
	if(file != NULL) {
		char H[5];
		int thisprefsversion;
		Read(file,H,5);
		Read(file,&thisprefsversion,sizeof(int));
		if(thisprefsversion<2) {
			printf("Your current '.prefs' file appears to be from a previous version!\n");
			printf("If you encounter problems, reset your Account settings ('Preferences/Program Settings') and select 'Newsgroups/Update Groups'\n");
		}
		Read(file,&nextID,sizeof(int));
		int entries = 0;
		Read(file,&entries,sizeof(int));
		clearGdata();
		if(account.grouplistType!=0) {
			tn_folders=(MUI_NListtree_TreeNode *)DoMethod(LISTTREE_groupdata,MUIM_NListtree_Insert,"Folders",NULL,MUIV_NListtree_Insert_ListNode_Root,MUIV_NListtree_Insert_PrevNode_Tail,TNF_LIST);
			tn_newsgroups=(MUI_NListtree_TreeNode *)DoMethod(LISTTREE_groupdata,MUIM_NListtree_Insert,"Newsgroups",NULL,MUIV_NListtree_Insert_ListNode_Root,MUIV_NListtree_Insert_PrevNode_Tail,TNF_LIST);
		}
		
		for(int k=0;k<entries;k++) {
			gdata=new GroupData();
			if(thisprefsversion<3)
				Read(file,gdata,sizeof(GroupData_v2));
			else
				Read(file,gdata,sizeof(GroupData));
			/*gdata->flags[0]=FALSE;
			gdata->flags[1]=FALSE;*/
			insertGdata(gdata,FALSE);
		}
		// still needed for NListtree ?
		/*if(account.grouplistType!=0)
			DoMethod(LISTTREE_groupdata,MUIM_NListtree_Insert,"",NULL,MUIV_NListtree_Insert_ListNode_Root,MUIV_NListtree_Insert_PrevNode_Tail,TNF_LIST);*/
		Close(file);
		file=NULL;
	}
	if(lock) {
		UnLock(lock);
		lock=NULL;
	}
}

BOOL init_data() {
	nLog("init_data() called\n");
	int k = 0;
	for(k=0;k<NSIGS;k++)
		sigs[k]=NULL;
	//load folder prefs
	// assign NewsCoaster:
	BPTR anlock = Lock("PROGDIR:",ACCESS_READ);
	if(anlock != NULL) {
		if(!AssignLock("NewsCoaster",anlock))
			UnLock(anlock);
		anlock=NULL;
	}
	
	// check users
	char usersfile[] = "NewsCoaster:.users";
	if(exists(usersfile)) {
		BPTR lock = Lock(usersfile,ACCESS_READ);
		BPTR file = Open(usersfile,MODE_OLDFILE);
		BOOL fail=FALSE;
		if(file != NULL) {
			short nousers = 0,logonreq = 0;
			Read(file,&nousers,sizeof(short));
			Read(file,&logonreq,sizeof(short));
			Seek(file,16*sizeof(short),OFFSET_CURRENT); // spare
			if(logonreq==TRUE) {
				set(wnd_login,MUIA_Window_Open,TRUE);
				set(wnd_login,MUIA_Window_ActiveObject,STR_login_USER);
				char name[USER_LEN+1]="";
				char pass[USER_LEN+1]="";
				BOOL loginrun=TRUE;
				while(loginrun) {
					switch(DoMethod(app,MUIM_Application_NewInput,&signal))
					{
					case LOGIN_OKAY:
						loginrun=FALSE;
						break;
					case LOGIN_CANCEL:
						loginrun=FALSE;
						fail=TRUE;
						break;
					}
					if(loginrun && signal)
						Wait(signal);
				}
				set(wnd_login,MUIA_Window_Open,FALSE);
				if(fail==FALSE) {
					// see if login is valid!
					currentUser = new User();
					BOOL okay=FALSE;
					do {
						if(Read(file,currentUser,sizeof(User))<=0)
							break;
						strncpy(name,getstr(STR_login_USER),USER_LEN); // must do each time, since fields are cleared by User::isValid()
						name[USER_LEN] = '\0';
						strncpy(pass,getstr(STR_login_PASS),USER_LEN);
						pass[USER_LEN] = '\0';
						okay = currentUser->isValid(name,pass);
					} while(okay==FALSE);
					if(!okay) {
						MUI_RequestA(app,0,0,"Login","_Okay","\33cLogin Failed!\nPlease try again with a correct login.",0);
						fail=TRUE;
					}
				}
			}
			else {
				// need to get dataLoc of this user
				currentUser = new User();
				Read(file,currentUser,sizeof(User));
			}
		}
		if(file) {
			Close(file);
			file=NULL;
		}
		if(lock) {
			UnLock(lock);
			lock=NULL;
		}
		if(fail)
			return FALSE;
	}
	else {
		// there is no '.users' file, so ask for a new user
		set(CM_newuser_SUP,MUIA_Disabled,TRUE); // MUST have supervisor for first user
		set(CM_newuser_COPYPREFS,MUIA_Disabled,TRUE); // this one makes no sense
		set(wnd_newuser,MUIA_Window_Open,TRUE);
		char name[16]="";
		char pass[16]="";
		int val = 0;
		while(newuseradded==0) {
			do_input();
			get(wnd_newuser,MUIA_Window_Open,&val);
			if(val==FALSE) {
				if(newuseradded==0)
					newuseradded=-1;
			}
			if((newuseradded==0) && signal)
				Wait(signal);
		}
		set(CM_newuser_SUP,MUIA_Disabled,FALSE);
		set(CM_newuser_COPYPREFS,MUIA_Disabled,FALSE);
		if(newuseradded!=1)
			return FALSE;
	}
	if(currentUser->isSupervisor())
		set(menuitem_USERS,MUIA_Menuitem_Enabled,TRUE);
	else
		set(menuitem_USERS,MUIA_Menuitem_Enabled,FALSE);
	loadUsers();
	// assign NewsCoasterData:
	//lock=Lock(ncdata_folder,ACCESS_READ);
	if(!exists(currentUser->dataLocation)) {
		int result=MUI_RequestA(app,0,0,"Startup","_Continue|Quit","\33cLogin Error!\nThe news directory for this login does not exist!\nYou may either quit and log in with a different username,\nor continue with the news directory set to 'PROGDIR:'",0);
		if(result==1)
			strcpy(currentUser->dataLocation,"PROGDIR:");
		else
			return FALSE;
	}
	assignNewsCoasterData:
	BOOL success=FALSE;
	BPTR andlock = Lock(currentUser->dataLocation,ACCESS_READ);
	if(andlock) {
		if(!AssignLock("NewsCoasterData",andlock))
			UnLock(andlock);
		else
			success=TRUE;
		andlock=NULL;
	}
	if(success==FALSE) {
		if(strcmp(currentUser->dataLocation,"PROGDIR:")==0) {
			MUI_RequestA(app,0,0,"Startup","_Okay","\33cLogin Fatal Error!\nThe news directory 'PROGDIR:' could not be accessed!",0);
			return FALSE;
		}
		else {
			int result=MUI_RequestA(app,0,0,"Startup","_Continue|Quit","\33cLogin Error!\nThe news directory for this login could not be accessed!\nYou may either quit and log in with a different username,\nor continue with the news directory set to 'PROGDIR:'",0);
			if(result==1) {
				strcpy(currentUser->dataLocation,"PROGDIR:");
				goto assignNewsCoasterData;
			}
			else
				return FALSE;
		}
	}
	char filename[]="NewsCoasterData:.prefs";
	BPTR lock = Lock(filename,ACCESS_READ);
	BOOL bakup=FALSE;
	//Read info...
	BPTR file=Open(filename,MODE_OLDFILE);
	if(file != NULL) {
		char H[5] = "";
		int thisprefsversion = 0;
		Read(file,H,5);
		Read(file,&thisprefsversion,sizeof(int));
		if(thisprefsversion<2) {
			printf("Your current '.prefs' file appears to be from a previous version!\n");
			printf("If you encounter problems, reset your Account settings ('Preferences/Program Settings') and select 'Newsgroups/Update Groups'\n");
		}
		if(thisprefsversion<prefsversion)
			bakup=TRUE;
		Read(file,&nextID,sizeof(int));
		int entries=0;
		Read(file,&entries,sizeof(int));
		BOOL out_folder=FALSE;
		BOOL sent_folder=FALSE;
		BOOL delete_folder=FALSE;
		tn_folders=(MUI_NListtree_TreeNode *)DoMethod(LISTTREE_groupdata,MUIM_NListtree_Insert,"Folders",NULL,MUIV_NListtree_Insert_ListNode_Root,MUIV_NListtree_Insert_PrevNode_Tail,TNF_LIST);
		tn_newsgroups=(MUI_NListtree_TreeNode *)DoMethod(LISTTREE_groupdata,MUIM_NListtree_Insert,"Newsgroups",NULL,MUIV_NListtree_Insert_ListNode_Root,MUIV_NListtree_Insert_PrevNode_Tail,TNF_LIST);
		
		GroupData ** gdataptr=NULL;
		//printf("%d\n",thisprefsversion);
		//printf("->%d\n",prefsversion);
		if(entries>0) {
			// argh, we have the group data stored before the account, so we store the info
			//gdataptr=(GroupData **)AllocVec(entries*sizeof(GroupData *),MEMF_PUBLIC|MEMF_CLEAR);
			gdataptr = new GroupData *[entries];
			for(k=0;k<entries;k++) {
				GroupData *gdata = new GroupData();
				gdataptr[k] = gdata;
				//printf("%d : %d , %d\n",gdata,&gdata->ID,gdata->unused);
				if(thisprefsversion<3)
					Read(file,gdata,sizeof(GroupData_v2));
				else
					Read(file,gdata,sizeof(GroupData));
				//Read(file,gdata,sizeof(GroupData));
				//printf("%d : %s\n",gdata->ID,gdata->name);
				//printf("Read :%s\n",gdata->name);
				gdata->flags[0]=FALSE;
				gdata->flags[1]=FALSE;
				if(gdata->ID==-1)
					out_folder=TRUE;
				else if(gdata->ID==-2)
					sent_folder=TRUE;
				else if(gdata->ID==-3)
					delete_folder=TRUE;
				//printf("ver: %f ID: %d\n",account.version,gdata->serverID);
				//printf("ID: %d\n",gdata->serverID);
				
				// but if this folder has otherwise been deleted, they need to be created again!
				makeFolder(gdata->ID);
				
			}
		}
		// patch for bug - Account size change as of v1.28! (from 5832 to 5676)
		//if(thisprefsversion<4)
		/*{
			BOOL okay=TRUE;
			LONG pos=Seek(file,0,OFFSET_CURRENT);
			LONG fpos=pos;
			Seek(file,0,OFFSET_END);
			LONG len=Seek(file,0,OFFSET_CURRENT)+1;
			Seek(file,pos,OFFSET_BEGINNING);
			fpos += sizeof(Account);
			if(fpos>len)
				okay=FALSE;
			else {
				Seek(file,sizeof(Account),OFFSET_CURRENT);
				// check sigs are stored correctly
				for(k=0;k<NSIGS;k++)
				{
					if(Read(file,&temp,sizeof(int))==0) {
						okay=FALSE;
						break;
					}
					fpos += temp;
					if(fpos>len) {
						okay=FALSE;
						break;
					}
					Seek(file,temp,OFFSET_CURRENT);
				}
			}
			Seek(file,pos,OFFSET_BEGINNING);
			if(okay) {
				Read(file,&account,sizeof(Account));
				// but still might fail!
			}
			if(!okay) { // not 'else' because may fail if the if(okay) bit!
				printf("Patching..\n");
				int endbit = 1676;
				Read(file,&account,5676-endbit);
				Seek(file,156,OFFSET_CURRENT);
				char * ptr = &account;
				ptr = ptr + 5676 - endbit;
				Read(file,ptr,endbit);
			}
		}*/
		BOOL accread = FALSE;
		if(FORCEPATCH1) {
			if(thisprefsversion<4) {
				printf("Patching..\n");
				int endbit = 1676;
				Read(file,&account,5676-endbit);
				Seek(file,156,OFFSET_CURRENT);
				char * ptr = (char *)&account;
				ptr = ptr + 5676 - endbit;
				Read(file,ptr,endbit);
				accread=TRUE;
			}
			else
				printf("FORCEPATCH1 only needed for prefs versions previous to v4\n");
		}
		if(!accread)
			Read(file,&account,sizeof(Account));
		if(account.readheader_first==0) {
			account.readheader_first=1;
			account.readheader_type=1;
			strcpy(account.readheaders,"From|To|Newsgroups|Date|Subject|Followup-To|Reply-To");
		}
		if(thisprefsversion<4)
			strcpy(account.followup_text,"On %d, %n wrote:");
		if(nlisttree==FALSE) {
			account.grouplistType = 0;
			account.mdata_view = 0;
		}
		// insert group data
		if(gdataptr!=NULL) {
			for(k=0;k<entries;k++) {
				if(account.version<1.325)
					gdataptr[k]->serverID = 0;
				insertGdata(gdataptr[k],FALSE);
			}
			//FreeVec(gdataptr);
			delete [] gdataptr;
			gdataptr=NULL;
		}
		
		if(!out_folder)
			createOutgoing();
		if(!sent_folder)
			createSent();
		if(!delete_folder)
			createDeleted();
		
		for(k=0;k<NSIGS;k++) {
			int temp = 0;
			if(Read(file,&temp,sizeof(int))==0)
				break;
			if(temp>0) {
				sigs[k] = new char[temp+256];
				if(sigs[k]!=NULL) {
					/*if(Read(file,sigs[k],temp)==0)
						break;*/
					int read = Read(file,sigs[k],temp);
					if(read <= 0) {
						sigs[k][0] = 0;
						break;
					}
					else
						sigs[k][read] = 0;
				}
				else
					Seek(file,temp,OFFSET_CURRENT);
			}
		}
		if(account.mimeprefsno>256)
			account.mimeprefsno=0;
		for(k=0;k<account.mimeprefsno;k++) {
			account.mimeprefs[k]=new MIMEPrefs;
			if(Read(file,account.mimeprefs[k],sizeof(MIMEPrefs))<=0) {
				delete account.mimeprefs[k];
				account.mimeprefsno=k;
				break;
			}
		}
		if(account.linelength<4)
			account.linelength=72;
		else if(account.linelength>256)
			account.linelength=256;
		if(account.version<1.315 || account.port==0)
			account.port=119;
	}
	else {
		account.readheader_first=1;
		account.readheader_type=1;
		strcpy(account.readheaders,"From|To|Newsgroups|Date|Subject|Followup-To|Reply-To");
		//outgoing
		createOutgoing();
		createSent();
		createDeleted();
		strcpy(account.name,"Lazy Person");
		strcpy(account.email,"me@wherever.com");
		strcpy(account.nntp,"news");
		strcpy(account.nntppost,"");
		strcpy(account.smtp,"mail");
		strcpy(account.domain,"userid");
		account.nntp_auth=FALSE;
		strcpy(account.user,"");
		strcpy(account.password,"");
		//account.usesig=TRUE;
		account.sentID=0;
		Locale * locale = OpenLocale(NULL);
		if(locale!=NULL)
			account.timezone=-(int)(locale->loc_GMTOffset/60);
		else
			account.timezone=0;
		account.bst=FALSE;
		strcpy(account.followup_text,"On %d, %n wrote:");
		account.killfiles=0;
		account.mimeprefsno=0;
		account.linelength=72;
		account.rewrap=0; // turn off as default due to it sometimes causing problems (eg, lines starting with a smiley when they aren't quoted bits..)
		account.xno=2; // put in X-No-Archive on replies that were X-No-Archive'd
		account.use_sizekill=0;
		account.multiplevws=TRUE;
		account.flags= Account::SNIPSIG | Account::LOGDEL;
		strcpy(account.defviewer,"sys:utilities/multiview \"%s\" FONTNAME=\"topaz\" FONTSIZE=8");
		account.port = 119;
	}
	if(account.listflags == 0)
		account.listflags = Account::LISTUPDATE | Account::LISTFLAGS | Account::LISTFROMGROUP | Account::LISTDATE | Account::LISTSUBJECT;
	if(account.weightHD<=0 || account.weightMESS<=0) {
		account.weightHD=50;
		account.weightMESS=100;
	}
	if(account.weightGLIST<=0 || account.weightMLIST<=0) {
		account.weightGLIST=100;
		account.weightMLIST=200;
	}
	set(grouplistGroup,MUIA_HorizWeight,account.weightGLIST);
	set(messageGroup,MUIA_HorizWeight,account.weightMLIST);
	if(file) {
		Close(file);
		file=NULL;
	}
	if(lock) {
		UnLock(lock);
		lock=NULL;
	}
	if(account.sorttypedir==0) {
		account.sorttype=1;
		account.sorttypedir=1;
	}
	if(bakup)
		Execute("copy NewsCoasterData:.prefs NewsCoasterData:.prefs.bak",NULL,NULL);
	if(exists("NewsCoasterData:.servers"))
		load_servers();
	else {
		// create from Account (legacy)
		Server *server = new Server();
		strcpy(server->nntp,account.nntp);
		strcpy(server->user,account.user);
		strcpy(server->password,account.password);
		server->nntp_auth = account.nntp_auth;
		server->port = account.port;
		server->def = TRUE;
		if(*account.nntppost==0)
			server->post = TRUE;
		else
			server->post = FALSE;
		server->ID = nextServerID++;
		strcpy(server->lastGotGroups,account.lastGotGroups);
		DoMethod(NLIST_acc_SERVERS,MUIM_NList_InsertSingle,server,MUIV_NList_Insert_Bottom);
		if(*account.nntppost!=0) {
			Server *serverp=new Server;
			strcpy(serverp->nntp,account.nntppost);
			strcpy(serverp->user,"");
			strcpy(serverp->password,"");
			serverp->nntp_auth = FALSE;
			serverp->port = 119;
			serverp->def = FALSE;
			serverp->post = TRUE;
			serverp->ID = nextServerID++;
			DoMethod(NLIST_acc_SERVERS,MUIM_NList_InsertSingle,serverp,MUIV_NList_Insert_Bottom);
		}
		save_servers();
	}
	load_killfile();
	account.save_data();
	
	char logfile[]="NewsCoaster:newscoaster.log";
	if((account.flags & Account::LOGDEL)!=0)
		DeleteFile(logfile);
	logFile=Open(logfile,MODE_READWRITE);
	if(logFile==NULL && (account.flags & Account::LOGGING)!=0)
		printf("Error! - Unable to open file '%s'!\n",logfile);
	else if(logFile != NULL) {
		Seek(logFile,0,OFFSET_END);
		if((account.flags & Account::LOGDEL)==0)
			nLog("\n\n");
	}
	nLog("NewsCoaster started\n");
	nLog("  version %s\n",version);

	resetMessageListFormat();
	return TRUE;
}

void Account::save_data() {
	nLog("Account::save_data() called\n");
	int k = 0;
	int entries = 0,trueentries = 0;
	BPTR file = NULL;
	int temp = 0;
	//char filename[MAXFILENAME] = "";
	// initial stuff
	get(grouplistGroup,MUIA_HorizWeight,&account.weightGLIST);
	get(messageGroup,MUIA_HorizWeight,&account.weightMLIST);
	//save folder prefs
	GroupData * gdata;
	char filename[]="NewsCoasterData:.prefs";
	DeleteFile(filename);
	entries=0;
	getGdataEntries(&entries);
	getGdataTrueEntries(&trueentries);
	//Write info...
	file=Open(filename,MODE_NEWFILE);
	if(file)
	{
		nLog("  writing header\n");
		char Header[]="NRGD";
		Write(file,Header,5);
		Write(file,&prefsversion,sizeof(int));
		Write(file,&nextID,sizeof(int));
		Write(file,&trueentries,sizeof(int));
		nLog("  writing groups\n");
		if(entries>0)
		{
			for(k=0;k<entries;k++)
			{
				getGdata(k,&gdata);
				if(gdata==NULL)
					continue;
				Write(file,gdata,sizeof(GroupData));
			}
		}
		nLog("  writing account\n");
		account.version = ver;
		Write(file,this,sizeof(Account));
		nLog("  writing .sigs\n");
		for(k=0;k<NSIGS;k++)
		{
			if(sigs[k])
			{
				temp=strlen(sigs[k])+1;
				Write(file,&temp,sizeof(int));
				if(temp>0)
					Write(file,sigs[k],temp);
			}
			else
			{
				temp=0;
				Write(file,&temp,sizeof(int));
			}
		}
		nLog("  writing mimeprefs\n");
		if(mimeprefsno>0)
		{
			for(k=0;k<mimeprefsno;k++)
			{
				Write(file,mimeprefs[k],sizeof(MIMEPrefs));
			}
		}
		nLog("  writing complete\n");
	}
	if(file)
	{
		Close(file);
		file=NULL;
	}
	nLog("  finished\n");
}

void Account::save_tofile(char *filename) {
	nLog("Account::save_tofile((char *)%s) called\n",filename);
	int k = 0;
	BPTR file = NULL;
	int temp = 0;
	//save folder prefs
	DeleteFile(filename);
	int entries = 0;
	//Write info...
	file=Open(filename,MODE_NEWFILE);
	if(file)
	{
		char Header[]="NRGD";
		Write(file,Header,5);
		Write(file,&prefsversion,sizeof(int));
		Write(file,&nextID,sizeof(int));
		Write(file,&entries,sizeof(int));
		Write(file,this,sizeof(Account));
		for(k=0;k<NSIGS;k++)
		{
			// write empty sigs
			{
				temp=0;
				Write(file,&temp,sizeof(int));
			}
		}
		if(mimeprefsno>0)
		{
			for(k=0;k<mimeprefsno;k++)
			{
				Write(file,mimeprefs[k],sizeof(MIMEPrefs));
			}
		}
	}
	if(file)
	{
		Close(file);
		file=NULL;
	}
}

void free_data() {
	nLog("free_data() called\n");
	GroupData * gdata=NULL;
	StatusWindow * statusWindow = new StatusWindow(app,"Shutting Down..");

	statusWindow->setText("closing sockets..");
	closeSockets();
	int k = 0;
	// update deleted folder to 0 entries (see later for actual deletion)
	get_gdata(&gdata,-3);
	gdata->nummess=0;
	gdata->num_unread=0;

	statusWindow->setText("saving preferences..");
	account.save_data();

	statusWindow->setText("saving killfile..");
	save_killfile();

	statusWindow->setText("saving servers..");
	save_servers();
	getGdataDisplayed(&gdata);
	if(gdata->flags[1]) {
		statusWindow->setText("writing index..");
		write_index(0);
	}

	statusWindow->setText("freeing memory..");
	for(k=0;k<NSIGS;k++) {
		if(sigs[k]) {
			delete [] sigs[k];
			sigs[k]=NULL;
		}
	}
	freeServerCycle();
	if(currentUser != NULL) {
		delete currentUser;
		currentUser = NULL;
	}
	ViewWindow::freeStatics();
	WriteWindow::freeStatics();

	statusWindow->setText("deleting files..");
	Execute("delete >NIL: NewsCoasterData:nc_tempfile#?",NULL,NULL);
	//Execute("delete >NIL: RAM:nc_tempfile#?",NULL,NULL);
	Execute("delete >NIL: NewsCoasterData:deleted/#?",NULL,NULL);
	//Execute("copy NewsCoaster:default.index NewsCoasterData:deleted/.index",NULL,NULL);
	writeEmptyIndex(-3);

	// remove assign
	/*lock=Lock("PROGDIR:",ACCESS_READ);
	if(lock)
	{
		RemAssignList("NewsCoaster",lock);
		UnLock(lock);
		lock=NULL;
	}*/
	/*Execute("assign NewsCoaster: >NIL",NULL,NULL);
	Execute("assign NewsCoasterData: >NIL",NULL,NULL);*/

	delete statusWindow;
	nLog("  free_data() completed\n");
}

void delete_mess(GroupData * gdata,MessageListData * mdata,BOOL visible,BOOL close) {
	GroupData * gdatatemp=NULL;
	// mdata need not be a copy
	int k = 0,l = 0;
	sleepAll(TRUE);
	if(visible) {
		nLog("delete_mess((GroupData *)%d,(MessageListData)%d,(BOOL)%d,(BOOL)close) called\n",gdata,mdata,visible,close);
		getGdataDisplayed(&gdatatemp);
		getGdataActivePos(&k);
		getMdataActivePos(&l);
		setGdataQuiet(TRUE);
		setMdataQuiet(TRUE);
		//clearThreadView();
	}

	delete_file(gdata,mdata);
	write_index_delete(gdata,mdata);
	gdata->nummess--;
	if(mdata->flags[1])
		gdata->num_unread--;

	mdata = NULL;

	if(visible)
		setEnabled();

	//gdata->flags[1]=TRUE;
	if(visible) {
		//setGdataActive(k);
		//gdata_readID=gdatatemp->ID;
		redrawGdataAll();
		GroupData * cdg = NULL;
		getGdataDisplayed(&cdg);
		if(cdg->ID == gdata->ID) {
			write_index(0);
			threadView();
		}
		/*
		setGdataQuiet(FALSE);
		if(gdatatemp->ID == gdata->ID)

		set_and_read(gdatatemp,FALSE);
		setMdataActive(l);*/

		setMdataQuiet(FALSE);
	}
	sleepAll(FALSE);
}

void delete_mess(GroupData * gdata,MessageListData * mdata,BOOL visible)
{ delete_mess(gdata,mdata,visible,TRUE); }

void move(GroupData * gdata,GroupData * gdata2,MessageListData * mdata,int type,BOOL visible,BOOL multi,BOOL close) {
	if(!multi) {
		nLog("move((GroupData *)%d,(GroupData *)%d,(MessageListData *)%d,(int)%d,(BOOL)%d,(BOOL)%d,(BOOL)%d) called\n",gdata,gdata2,mdata,type,visible,multi,close);
	}
	// mdata *must* be a copy (but we may delete it after the function is used)
	//type: 0=move, 1=copy
	// todo
	/*if(view_gdata.ID == gdata->ID && view_mdata.ID == mdata->ID && close==TRUE && type==0)
		set(wnd_view,MUIA_Window_Open,FALSE);*/
	if(type==0 && close==TRUE)
		ViewWindow::checkDeleted(gdata->ID,mdata->ID);
	sleepAll(TRUE);

	GroupData * gdatatemp=NULL;
	char buffer[256]="";
	char buffer2[256]="";
	char command[512]="";
	int l = 0;
	getGdataDisplayed(&gdatatemp);
	getMdataActivePos(&l);
	getFilePath(buffer,gdata->ID,mdata->ID);

	for(;;) { // we want a file that doesn't exist!
		/*if(gdata2->ID==-1)
			sprintf(buffer2,"NewsCoasterData:outgoing/news_%d",gdata2->nextmID);
		else if(gdata2->ID==-2)
			sprintf(buffer2,"NewsCoasterData:sent/news_%d",gdata2->nextmID);
		else if(gdata2->ID==-3)
			sprintf(buffer2,"NewsCoasterData:deleted/news_%d",gdata2->nextmID);
		else if(gdata2->ID>=0)
			sprintf(buffer2,"NewsCoasterData:folder_%d/news_%d",gdata2->ID,gdata2->nextmID);*/
		getFilePath(buffer2,gdata2->ID,gdata2->nextmID);
		if(exists(buffer2))
			gdata2->nextmID++;
		else
			break;
	}

	if(type==0) {
		if(DEBUG)
			printf("DEBUG: calling: Rename(\"%s\",\"%s\")\n",buffer,buffer2);
		Rename(buffer,buffer2);
		if(DEBUG) {
			sprintf(command,"The program has paused after moving a message.\nIf you are having problems with this, please check to see if the file\n%s still exists,\nand also if the file\n%s has now been created.\nWhat are the contents of those files?",buffer,buffer2);
			MUI_RequestA(app,0,0,"DEBUG","_Continue",command,0);
		}
	}
	else if(type==1) {
		char tempname[64] = "";
		sprintf(tempname,"NewsCoasterData:news_temp_%d",mdata->ID);
		sprintf(command,"Copy %s to %s",buffer,tempname);
		if(DEBUG)
			printf("DEBUG: executing: %s\n",command);
		Execute(command,NULL,NULL);
		while(!Rename(tempname,buffer2)) {
			gdata2->nextmID++;
			getFilePath(buffer2,gdata2->ID,gdata2->nextmID);
		}
	}
	int nmID = gdata2->nextmID;
	if(type == 0) {
		int i=0;
		int entries = 0;
		// check search window
		get(NLIST_search_RES,MUIA_NList_Entries,&entries);
		for(i=0;i<entries;i++) {
			MessageListData *mdata2 = NULL;
			DoMethod(NLIST_search_RES,MUIM_NList_GetEntry,i,&mdata2);
			if(mdata->ID == mdata2->ID && gdata->ID == mdata2->flags[6]) {
				mdata2->ID = nmID;
				mdata2->flags[6] = gdata2->ID;
				break;
			}
		}
		// check join window
		get(NLIST_joinmsgs_MSGS,MUIA_NList_Entries,&entries);
		for(i=0;i<entries;i++) {
			MessageListData *mdata2 = NULL;
			DoMethod(NLIST_joinmsgs_MSGS,MUIM_NList_GetEntry,i,&mdata2);
			if(mdata->ID == mdata2->ID && gdata->ID == mdata2->flags[6]) {
				mdata2->ID = nmID;
				mdata2->flags[6] = gdata2->ID;
				break;
			}
		}
	}

	if(type==0) {
		if(gdatatemp->ID!=gdata->ID)
			set_and_read(gdata);
	}
	int tID=mdata->ID;
	int old_pos = get_mdata_pos(tID);
	mdata->ID = nmID;
	gdata2->nextmID++;
	if(gdata2->ID!=-3) // articles in 'deleted' remember where they came from
		mdata->flags[6]=gdata2->ID;
	if(multi==FALSE) {
		gdata2->nummess++;
		if(mdata->flags[1])
			gdata2->num_unread++;
		write_index_single(gdata2,mdata);
		setEnabled();
		//if(type==0)
		//	clearThreadView();
	}
	if(type==0) {
		if(old_pos != -1) {
			DoMethod(NLIST_messagelistdata,MUIM_NList_Remove,old_pos);
			if(!multi) {
				threadView();
				setEnabled();
			}
			gdata->nummess--;
			if(mdata->flags[1])
				gdata->num_unread--;
			if(visible) {
				write_index(0);
				if(gdatatemp->ID!=gdata->ID)
					set_and_read(gdatatemp);
			}
		}
	}
	sleepAll(FALSE);
	// we really should save the changed group info as soon as possible;
	// for multiple moves, this should be done after all the moves
	if(multi==FALSE)
		account.save_data();
	redrawGdataAll();
	setMdataActive(l);
}

void move(GroupData * gdata,GroupData * gdata2,MessageListData * mdata,int type,BOOL visible,BOOL multi)
{ move(gdata,gdata2,mdata,type,visible,multi,TRUE); }

void move_n(GroupData * gdata,GroupData * gdata2,MessageListData * mdataptr,int n,int type,StatusWindow *statusWindow) {
	//nLog("move_n((GroupData *)%d,(GroupData *)%d,(MessageListData *)%d,(int)%d,(int)%d,(BOOL)%d) called\n",gdata,gdata2,mdataptr,n,type,visible);
	nLog("move_n((GroupData *)%d,(GroupData *)%d,(MessageListData *)%d,(int)%d,(int)%d,(StatusWindow *)%d) called\n",gdata,gdata2,mdataptr,n,type,statusWindow);
	// mdata *must* be a copy (but we may delete it after the function is used)
	// type: 0=move, 1=copy
	// todo
	//if(view_gdata.ID == gdata->ID && view_mdata.ID == mdata->ID && close==TRUE && type==0)
	//	set(wnd_view,MUIA_Window_Open,FALSE);
	//if(visible)
	//	WriteWindow::sleepAll(TRUE);
	if(type==0) {
		for(int i=0;i<n;i++)
			ViewWindow::checkDeleted(gdata->ID,mdataptr[i].ID);
	}
	GroupData * gdatatemp=NULL;
	char buffer[64]="";
	char buffer2[64]="";
	char command[256]="";
	int l=0;
	getGdataDisplayed(&gdatatemp);
	getMdataActivePos(&l);
	if(gdata->ID==-1)
		sprintf(buffer,"NewsCoasterData:outgoing/news_");
	else if(gdata->ID==-2)
		sprintf(buffer,"NewsCoasterData:sent/news_");
	else if(gdata->ID==-3)
		sprintf(buffer,"NewsCoasterData:deleted/news_");
	else if(gdata->ID>=0)
		sprintf(buffer,"NewsCoasterData:folder_%d/news_",gdata->ID);
	char *ptr = &buffer[ strlen(buffer) ];

	if(gdata2->ID==-1)
		sprintf(buffer2,"NewsCoasterData:outgoing/news_");
	else if(gdata2->ID==-2)
		sprintf(buffer2,"NewsCoasterData:sent/news_");
	else if(gdata2->ID==-3)
		sprintf(buffer2,"NewsCoasterData:deleted/news_");
	else if(gdata2->ID>=0)
		sprintf(buffer2,"NewsCoasterData:folder_%d/news_",gdata2->ID);
	char *ptr2 = &buffer2[ strlen(buffer2) ];

	index_handler * ih = new index_handler(gdata2);

	int pos = get_gdataPos(gdata->ID);
	int pos2 = get_gdataPos(gdata2->ID);

	int i=0;
	int s_entries = 0;
	get(NLIST_search_RES,MUIA_NList_Entries,&s_entries);
	int j_entries = 0;
	get(NLIST_joinmsgs_MSGS,MUIA_NList_Entries,&j_entries);
	
	// move
	for(i=0;i<n;i++) {
		//DoMethod(app,MUIM_Application_InputBuffered);
		//if(i % 16 == 0) {
			do_input();
			if(statusWindow->isAborted()==TRUE || running==FALSE)
				break;
		//}

		for(;;) { // we want a file that doesn't exist!
			sprintf(ptr,"%d",mdataptr[i].ID);
			sprintf(ptr2,"%d",gdata2->nextmID);
			if(exists(buffer2))
				gdata2->nextmID++;
			else
				break;
		}
		
		int nmID = gdata2->nextmID;
		if(type == 0) {
			// check search window
			int j=0;
			for(j=0;j<s_entries;j++) {
				MessageListData *mdata2 = NULL;
				DoMethod(NLIST_search_RES,MUIM_NList_GetEntry,j,&mdata2);
				if(mdataptr[i].ID == mdata2->ID && gdata->ID == mdata2->flags[6]) {
					mdata2->ID = nmID;
					mdata2->flags[6] = gdata2->ID;
					break;
				}
			}
			// check join window
			for(j=0;j<j_entries;j++) {
				MessageListData *mdata2 = NULL;
				DoMethod(NLIST_joinmsgs_MSGS,MUIM_NList_GetEntry,j,&mdata2);
				if(mdataptr[i].ID == mdata2->ID && gdata->ID == mdata2->flags[6]) {
					mdata2->ID = nmID;
					mdata2->flags[6] = gdata2->ID;
					break;
				}
			}
		}

		if(type==0) {
			Rename(buffer,buffer2);
		}
		else if(type==1) {
			sprintf(command,"Copy %s to %s",buffer,buffer2);
			Execute(command,NULL,NULL);
		}
		int tID=mdataptr[i].ID;
		int old_pos = get_mdata_pos(tID);
		mdataptr[i].ID = nmID;
		gdata2->nextmID++;
		if(gdata2->ID!=-3) // articles in 'deleted' remember where they came from
			mdataptr[i].flags[6]=gdata2->ID;

		if(mdataptr[i].flags[1])
			gdata2->num_unread++;
		ih->write(&mdataptr[i]);

		if(type==0) {
			gdata->nummess--;

			if(mdataptr[i].flags[1])
				gdata->num_unread--;
			if(old_pos != -1) {
				DoMethod(NLIST_messagelistdata,MUIM_NList_Remove,old_pos);
			}
		}

		gdata2->nummess++;
		redrawGdataPos(pos);
		redrawGdataPos(pos2);

	}

	if(ih) {
		delete ih;
		ih = NULL;
	}

	//if(type==0)
	//	clearThreadView();

	if(type==0) {
		if(gdatatemp->ID!=gdata->ID)
			set_and_read(gdata);
		threadView();
		setEnabled();
		write_index(0);
		if(gdatatemp->ID!=gdata->ID)
			set_and_read(gdatatemp);
	}
	//if(visible) {
	//	set(wnd_main,MUIA_Window_Sleep,FALSE);
	//	WriteWindow::sleepAll(FALSE);
	//}
	// we really should save the changed group info as soon as possible
	account.save_data();

	setMdataActive(l);
}

//void readgrouplist(Server *server,Object * NLIST,int filepos) {
void readgrouplist(Server *server,int filepos) {
	//nLog("readgrouplist((Server *)%d,(Object *)%d,(int)%d) called\n",server,NLIST,filepos);
	nLog("readgrouplist((Server *)%d,(int)%d) called\n",server,filepos);
	Object *NLIST = NLIST_groupman;
	BPTR file=NULL,lock=NULL;
	char buffer[MAXLINE]="";
	char temp[256]="";
	char filename[300]="";
	sprintf(filename,"NewsCoasterData:%s.gl",server->nntp);
	const int CHUNK = 512;
	char **in_buffer = new char *[CHUNK];
	char **in_buffer_ptr = in_buffer;
	StatusWindow * statusWindow = new StatusWindow(app,"Reading group list..");
	statusWindow->setText("Reading group list..");
	lock=Lock(filename,ACCESS_READ);
	file=Open(filename,MODE_OLDFILE);
	int found=0;
	if(file) {
		Seek(file,filepos,OFFSET_BEGINNING);
		Flush(file);
		set(NLIST,MUIA_NList_Quiet,TRUE);
		DoMethod(NLIST,MUIM_NList_Clear);
		for(;;) {
			if(!FGets(file,buffer,MAXLINE))
				break;
			if(*buffer == '\0')
				break;
			found++;

			char *ptr = buffer;
			while(*ptr != ' ')
				ptr++;
			int len = (int)ptr - (int)buffer;
			char *in = new char[len + 4];

			ptr = buffer;
			char *ptr_in = in;
			while(*ptr != ' ')
				*ptr_in++ = *ptr++;

			int len2 = strlen(ptr);

			*ptr_in++ = ' ';
			*ptr_in++ = ptr[len2-3];
			*ptr_in++ = '\0';
			
			*in_buffer_ptr++ = in;

			DoMethod(app,MUIM_Application_InputBuffered);
			if(found % CHUNK == 0) {

				DoMethod(NLIST,MUIM_NList_Insert,in_buffer,CHUNK,MUIV_NList_Insert_Bottom);
				in_buffer_ptr = in_buffer;

				do_input();
				if(statusWindow->isAborted()==TRUE || running==FALSE)
					break;

				sprintf(temp,"Read %d Groups",found);
				statusWindow->setText(temp);
			}
		}

		int rest = found % CHUNK;
		if(rest > 0) {

			DoMethod(NLIST,MUIM_NList_Insert,in_buffer,rest,MUIV_NList_Insert_Bottom);
			in_buffer_ptr = in_buffer;

			DoMethod(app,MUIM_Application_InputBuffered);

			sprintf(temp,"Read %d Groups",found);
			statusWindow->setText(temp);
		}

		Close(file);
		file=NULL;
		statusWindow->setText("Sorting List..");
		DoMethod(NLIST,MUIM_NList_Sort);
		set(NLIST,MUIA_NList_Quiet,FALSE);
		sprintf(temp,"\33cFound %d Groups\n",found);
		MUI_RequestA(app,0,0,"Group Manager","_Okay",temp,0);
	}
	else {
		sprintf(buffer,"\33cThe file %s.gl does not exist!\nPlease select 'Fetch Group List' from\nthe Project Menu.",account.nntp);
		MUI_RequestA(app,0,0,"Group Manager","_Okay",buffer,0);
	}
	delete [] in_buffer;
	if(lock) {
		UnLock(lock);
		lock=NULL;
	}
	delete statusWindow;
	static char title[300]="";
	if(filepos!=0) { // new newsgroups only, so don't allow writing!
		//set(BT_groupman_WRITE,MUIA_Disabled,TRUE);
		sprintf(title,"Group Manager : New Groups for %s",server->nntp);
		set(wnd_groupman,MUIA_Window_Title,title);
	}
	else {
		//set(BT_groupman_WRITE,MUIA_Disabled,FALSE);
		sprintf(title,"Group Manager : %s",server->nntp);
		set(wnd_groupman,MUIA_Window_Title,title);
	}
	set(NLIST,MUIA_NList_Active,MUIV_NList_Active_Top);
}

/*void writegrouplist(Server *server) {
	nLog("writegrouplist((Server *)server) called\n",server);
	BPTR file=NULL;
	STRPTR out = NULL;
	char filename[MAXFILENAME]="";
	char filename2[MAXFILENAME]="";
	sprintf(filename,"NewsCoasterData:%s.gl",server->nntp);
	sprintf(filename2,"NewsCoasterData:%s.gl.bak",server->nntp);
	set(app,MUIA_Application_Sleep,TRUE);
	DeleteFile(filename2);
	Rename(filename,filename2);
	file=Open(filename,MODE_NEWFILE);
	int found=0;
	if(file) {
		Flush(file);
		set(NLIST_groupman,MUIA_NList_Quiet,TRUE);
		int entries = 0,k = 0;
		get(NLIST_groupman,MUIA_NList_Entries,&entries);
		for(k=0;k<entries;k++) {
			DoMethod(NLIST_groupman,MUIM_NList_GetEntry,k,&out);
			if(out!=NULL) {
				Write(file,out,strlen(out));
				Write(file,"\n",1);
			}
		}
		Close(file);
		file=NULL;
		set(NLIST_groupman,MUIA_NList_Quiet,FALSE);
	}
	set(app,MUIA_Application_Sleep,FALSE);
}*/

void Write_file(char * filename,char * pos,int len) {
	// should be %d and not %s !
	nLog("Write_file((char *)%s,(char *)%d,(int)%d) called\n",filename,pos,len);
	DeleteFile(filename);
	BPTR file;
	file=Open(filename,MODE_NEWFILE);
	if(file)
	{
		Write(file,pos,len);
		Close(file);
		file=NULL;
	}
	nLog("  finished Write_file()\n");
}

char * selectNG(char * title,char * text,BOOL internal,BOOL poster) {
	nLog("selectNG((char *)%s,(char *)%s,(BOOL)%d,(BOOL)%d) called\n",title,text,internal,poster);
	int k = 0;
	int entries = 0;
	getGdataEntries(&entries);
	//char ** ptrarr = (char **)AllocVec( (entries+1)*sizeof(char*),MEMF_PUBLIC|MEMF_CLEAR);
	char ** ptrarr = new char *[entries+1];
	int count=0;
	VOID * ptr = NULL;
	if(poster)
		ptrarr[count++]="poster";
	for(k=0;k<entries;k++)
	{
		getGdata(k,(GroupData **)&ptr);
		if(ptr==NULL)
			continue;
		if( ((GroupData *)ptr)->ID>=0 || internal==TRUE)
			ptrarr[count++]=((GroupData *)ptr)->name;
	}
	char * buttons[2];
	buttons[0]=new char[64]; strcpy(buttons[0],text);
	buttons[1]=new char[64]; strcpy(buttons[1],"Cancel");
	ChoiceList * choice = new ChoiceList(app,NULL,title,ptrarr,count,buttons,2);
	char * rstr = NULL;
	if(choice)
	{
		int res=choice->show();
		int sel=choice->getSelected();
		if(sel>=0 && res==0)
		{
			char * str = ptrarr[sel];
			rstr = new char[strlen(str) + 1];
			strcpy(rstr,str);
		}
		delete choice;
	}
	/*for(k=0;k<count;k++) {
		if(ptrarr[k])
			delete ptrarr[k];
	}*/
	if(ptrarr)
		delete [] ptrarr;
		//FreeVec(ptrarr);
	for(k=0;k<2;k++)
	{
		if(buttons[k])
			delete buttons[k];
	}
	return rstr;
}

void getNGChoice(char * title,char * text,Object * STR,BOOL poster) {
	nLog("getNGChoice((char *)%s,(char *)%s,(Object *)%d,(BOOL)%d) called\n",title,text,STR,poster);
	char *str = selectNG(title,text,FALSE,poster);
	char buffer[1024] = "";
	if(str) {
		char *cstr = NULL;
		get(STR,MUIA_String_Contents,&cstr);
		if(cstr) {
			char *nstr = NULL;
			if(*cstr=='\0') {
				// text box is empty
				nstr = new char[strlen(str) + 1];
				strcpy(nstr,str);
			}
			else {
				char *temp = strstr(cstr,str);
				while(temp != NULL) {
					BOOL ok = TRUE;
					ok = ok && ( temp == cstr || temp[-1] == ',' );
					if(ok)
						break;

					temp = strstr(&temp[1],str);
				}
				if(temp==NULL) {
					// append
					nstr = new char[strlen(cstr)+strlen(str)+2];
					sprintf(nstr,"%s,%s",cstr,str);
				}
				else {
					// remove
					char *temp2 = &temp[strlen(str)];
					char *temp3 = &cstr[strlen(cstr)];
					nstr = new char[strlen(cstr)+1];
					int t1 = (int)temp-(int)cstr;
					if(t1>0) {
						strncpy(nstr,cstr,t1);
						nstr[t1] = '\0';
					}
					if(t1>0 && temp2<temp3) {
						if(nstr[t1-1]==',' && *temp2==',')
							t1--;
					}
					if(temp2<temp3)
						strcpy(&nstr[t1],temp2);
					if(*nstr==',')
						sprintf(nstr,"%s",&nstr[1]);
					if(nstr[strlen(nstr)-1]==',')
						nstr[strlen(nstr)-1]=0;
				}
			}
			strcpy(buffer,nstr);
			set(STR,MUIA_String_Contents,buffer);
			if(nstr)
				delete [] nstr;
		}
		delete [] str;
	}		
}

void getUserEmail(GroupData * gdata,char * buffer) {
	if(gdata->moreflags[1])
		sprintf(buffer,"\"%s\" ",gdata->alt_name);
	else
		sprintf(buffer,"\"%s\" ",account.name);
	if(gdata->moreflags[2])
		sprintf(buffer,"%s<%s>",buffer,gdata->alt_email);
	else
		sprintf(buffer,"%s<%s>",buffer,account.email);
}

void move_multi(int m,char * dest) {
	nLog("move_multi((int)%d,(char *)%s) called\n",m,dest);
	int k = 0,l = 0;
	GroupData * gdata=NULL;
	GroupData * gdata2=NULL;
	MessageListData * mdata=NULL;
	MessageListData * mdata2=NULL;
	MessageListData *mdatalist=NULL;
	getGdataDisplayed(&gdata);
	//int entries = 0;
	//get(NLIST_messagelistdata,MUIA_NList_Entries,&entries);
	int entries = getMdataVisibleEntries();
	/*int selent = 0;
	if(account.mdata_view==0) {
		MUI_NList_GetSelectInfo info;
		DoMethod(NLIST_messagelistdata,MUIM_NList_GetSelectInfo,&info);
		selent=info.vnum;
	}
	else
		DoMethod(LISTTREE_messagelistdata,MUIM_NList_Select,MUIV_NList_Select_All,MUIV_NList_Select_Ask,&selent);
	if(selent>0) {*/
	if(entries > 0) {
		char * str=NULL;
		if(dest==NULL) {
			if(m==0)
				str=selectNG("Move to which group?","Move",TRUE,FALSE);
			else
				str=selectNG("Copy to which group?","Copy",TRUE,FALSE);
		}
		else {
			str = new char[strlen(dest) + 1];
			strcpy(str,dest);
		}
		if(str) {
			GroupData * gdata2 = NULL;
			get_gdata(&gdata2,str);
			if(gdata2==NULL)
				return;
			setMdataQuiet(TRUE);
			if( (gdata->ID != gdata2->ID) || m==1) { // copying to the same folder should be allowed!
				mdatalist = new MessageListData[entries];
				l=0;
				getGdataDisplayed(&gdata);
				for(k=0;k<entries;k++) {
					if(isMdataSelected(k)) {
						getMdataVisible(k,&mdata);
						mdatalist[l++] = *mdata;
					}
				}
				StatusWindow *statusWindow = new StatusWindow(app,"");
				set(wnd_main,MUIA_Window_Sleep,TRUE);
				WriteWindow::sleepAll(TRUE);
				if(l>0) {
					if(m==0) {
						statusWindow->setText("Moving..");
					}
					else
						statusWindow->setText("Copying..");
					move_n(gdata,gdata2,mdatalist,l,m,statusWindow);
				}
				delete statusWindow;
				set(wnd_main,MUIA_Window_Sleep,FALSE);
				WriteWindow::sleepAll(FALSE);
			}
			if(mdatalist) {
				delete [] mdatalist;
				mdatalist=NULL;
			}
			setMdataQuiet(FALSE);
			delete [] str;
		}
	}
	else {
		if(m==0)
			MUI_RequestA(app,0,0,"Move Message","_Okay","\33cNo messages to move!",0);
		else
			MUI_RequestA(app,0,0,"Copy Message","_Okay","\33cNo messages to copy!",0);
	}
}

void move_multi(int m) {
	move_multi(m,NULL);
}

void delete_multi(BOOL confirm,BOOL movedel) {
	nLog("delete_multi((BOOL)%d,(BOOL)%d) called\n",confirm,movedel);
			GroupData * gdata=NULL;
			GroupData * gdata2=NULL;
			MessageListData * mdata=NULL;
			MessageListData *mdatalist=NULL;
			LONG result = 0;
			//int entries = 0,k = 0,l = 0;
			int k=0,l=0;
			getGdataDisplayed(&gdata);
			if(movedel)
            get_gdata(&gdata2,-3);
 			//get(NLIST_messagelistdata,MUIA_NList_Entries,&entries);
			int entries = getMdataVisibleEntries();
			if(entries>0) {
				if(confirm==TRUE && account.noconfirmdel==FALSE)
				{
					if(gdata->ID==-1)
						result=MUI_RequestA(app,0,0,"Delete Message(s)","_Delete|_Cancel","\33cAre you sure you wish\nto Delete the selected Message(s)?\nWARNING - These messages have not been sent yet!",0);
					else
						result=MUI_RequestA(app,0,0,"Delete Message(s)","_Delete|_Cancel","\33cAre you sure you wish\nto Delete the selected Message(s)?",0);
				}
				if(result==1 || confirm==FALSE || account.noconfirmdel==TRUE)
				{
					setMdataQuiet(TRUE);
					//mdatalist=(MessageListData *)AllocVec(entries*sizeof(MessageListData),MEMF_PUBLIC|MEMF_CLEAR);
					mdatalist = new MessageListData[entries];
					l=0;
					for(k=0;k<entries;k++) {
						if(isMdataSelected(k)) {
							getMdataVisible(k,&mdata);
							/*mdatalist[l]=new MessageListData;
							*mdatalist[l++]=*mdata;*/
							mdatalist[l++]=*mdata;
						}
					}
					if(l>0)
					{
						StatusWindow *statusWindow = new StatusWindow(app,"Deleting..");
						statusWindow->setText("Deleting..");
						set(wnd_main,MUIA_Window_Sleep,TRUE);
						WriteWindow::sleepAll(TRUE);
						if(movedel)
							move_n(gdata,gdata2,mdatalist,l,0,statusWindow);
						else {
							//clearThreadView();
							for(k=0;k<l;k++) {
								//DoMethod(app,MUIM_Application_InputBuffered);
								//if(k % 16 == 0) {
									if(statusWindow->isAborted() || running==FALSE)
										break;
									do_input();
								//}
								delete_mess(gdata,&mdatalist[k],FALSE);
							}
							write_index(0);
							threadView();
							setEnabled();
							redrawGdataAll();
							account.save_data(); // update group info on disk!
						}
						delete statusWindow;
						set(wnd_main,MUIA_Window_Sleep,FALSE);
						WriteWindow::sleepAll(FALSE);
					}
					if(mdatalist) {
						//FreeVec(mdatalist);
						delete [] mdatalist;
						mdatalist=NULL;
					}
					setMdataQuiet(FALSE);
				}
			}
			else
				MUI_RequestA(app,0,0,"Delete Message","_Okay","\33cNo messages to delete!",0);
}

void delete_multi(BOOL confirm)
{
	GroupData * gdata=NULL;
	BOOL movedel=FALSE;
	getGdataDisplayed(&gdata);
	if(gdata->ID!=-3)
		movedel=TRUE;
	delete_multi(confirm,movedel);
}

void undelete_multi(BOOL confirm) {
	nLog("undelete_multi((BOOL)%d) called\n",confirm);
	GroupData * gdata=NULL;
	GroupData * gdata2=NULL;
	MessageListData * mdata=NULL;
	MessageListData *mdatalist=NULL;
	LONG result = 0;
	//int entries = 0,k = 0,l = 0;
	int k=0,l=0;
   get_gdata(&gdata,-3);
	//get(NLIST_messagelistdata,MUIA_NList_Entries,&entries);
	int entries = getMdataVisibleEntries();
	if(entries>0) {
		if(confirm)
			result=MUI_RequestA(app,0,0,"Undelete Message(s)","_Undelete|_Cancel","\33cAre you sure you wish\nto Undelete the selected Message(s)?",0);
		if(result==1 || confirm==FALSE) {
			setMdataQuiet(TRUE);
			mdatalist = new MessageListData[entries];
			l=0;
			for(k=0;k<entries;k++) {
				if(isMdataSelected(k)) {
					getMdataVisible(k,&mdata);
					mdatalist[l++]=*mdata;
				}
			}
			if(l>0) {
				//clearThreadView();
				StatusWindow *statusWindow = new StatusWindow(app,"Undeleting..");
				statusWindow->setText("Undeleting..");
				set(wnd_main,MUIA_Window_Sleep,TRUE);
				WriteWindow::sleepAll(TRUE);
				for(k=0;k<l;k++) {
					//DoMethod(app,MUIM_Application_InputBuffered);
					//if(k % 16 == 0) {
						do_input();
						if(statusWindow->isAborted()==TRUE || running==FALSE)
							break;
					//}
		         get_gdata(&gdata2,mdatalist[k].flags[6]);
					move(gdata,gdata2,&mdatalist[k],0,FALSE,FALSE);
				}
				delete statusWindow;
				set(wnd_main,MUIA_Window_Sleep,FALSE);
				WriteWindow::sleepAll(FALSE);
				write_index(0);
				threadView();
				setEnabled();
				redrawGdataAll();
			}
			if(mdatalist) {
				delete [] mdatalist;
				mdatalist=NULL;
			}
			setMdataQuiet(FALSE);
		}
	}
	else
		MUI_RequestA(app,0,0,"Undelete Message","_Okay","\33cNo messages to Undelete!",0);
}

void deleteFolderContents(GroupData *gdata) {
	nLog("deleteFolderContents((GroupData *)%d) called\n",gdata);
	char buffer[300]="";
	if(gdata->ID==-1)
		sprintf(buffer,"delete >NIL: NewsCoasterData:outgoing/news_#?");
	else if(gdata->ID==-2)
		sprintf(buffer,"delete >NIL: NewsCoasterData:sent/news_#?");
	else if(gdata->ID==-3)
		sprintf(buffer,"delete >NIL: NewsCoasterData:deleted/news_#?");
	else if(gdata->ID>=0)
		sprintf(buffer,"delete >NIL: NewsCoasterData:folder_%d/news_#?",gdata->ID);
	Execute(buffer,NULL,NULL);

	// read in ID history
	int s_entries = 0;
	get(NLIST_search_RES,MUIA_NList_Entries,&s_entries);
	int j_entries = 0;
	get(NLIST_joinmsgs_MSGS,MUIA_NList_Entries,&j_entries);
	Vector * vector = new Vector(2048);
	read_index(gdata,vector);
	int n_mdata = vector->getSize();
	for(int i=0;i<n_mdata;i++) {
		int j=0;
		MessageListData *mdata=((MessageListData **)vector->getData())[i];
		ViewWindow::checkDeleted(gdata->ID,mdata->ID);

		// check search window
		for(j=0;j<s_entries;j++) {
			MessageListData *mdata2 = NULL;
			DoMethod(NLIST_search_RES,MUIM_NList_GetEntry,j,&mdata2);
			if(mdata->ID == mdata2->ID && gdata->ID == mdata2->flags[6]) {
				DoMethod(NLIST_search_RES,MUIM_NList_Remove,j);
				DoMethod(NLIST_search_RES,MUIM_NList_Redraw,MUIV_NList_Redraw_All);
				break;
			}
		}
		// check join window
		for(j=0;j<j_entries;j++) {
			MessageListData *mdata2 = NULL;
			DoMethod(NLIST_joinmsgs_MSGS,MUIM_NList_GetEntry,j,&mdata2);
			if(mdata->ID == mdata2->ID && gdata->ID == mdata2->flags[6]) {
				DoMethod(NLIST_joinmsgs_MSGS,MUIM_NList_Remove,j);
				DoMethod(NLIST_joinmsgs_MSGS,MUIM_NList_Redraw,MUIV_NList_Redraw_All);
				break;
			}
		}
	}
	if(vector!=NULL) {
		for(int i=0;i<vector->getSize();i++)
			delete vector->getData()[i];
		delete vector;
	}

	writeEmptyIndex(gdata->ID);
	gdata->nummess = 0;
	gdata->num_unread = 0;
	gdata->flags[1] = FALSE;
	GroupData *gdata2;
	getGdataDisplayed(&gdata2);
	if(gdata->ID == gdata2->ID)
		read_index();

}

void deleteFolderContents() {
	nLog("deleteFolderContents() called\n");
	GroupData * gdata = NULL;
	getGdataDisplayed(&gdata);
	deleteFolderContents(gdata);
}

void killmess(GroupData * gdata,MessageListData * mdata,int type) {
	// type: -1=ask user, otherwise 0,1,2 = type, +4=this group only, else, all groups
	nLog("killmess((GroupData *)%d,(MessageListData *)%d,(int)%d) called\n",gdata,mdata,type);
	NewMessage message;
	strcpy(message.getThisHeader,"nntp-posting-host:");
	get_refs(&message,gdata,mdata,GETREFS_NONE);

	int res=0,sel=0;
	int k=0;
	int expiretype=0,expire=0;
	int b_mid = -1;
	int b_nph = -1;
	set(wnd_killfile,MUIA_Window_Sleep,TRUE);
	if(type==-1) {
		char * ptrarr[5];
		int count = 0;
		ptrarr[count]=new char[64]; strcpy(ptrarr[count],"Messages from this Author");
			count++;
		ptrarr[count]=new char[64]; strcpy(ptrarr[count],"Messages in Response to Message");
			count++;
		ptrarr[count]=new char[64]; strcpy(ptrarr[count],"All Messages with the same Subject");
			count++;
		{
			char *ptr = strchr(message.messageID,'@');
			if(ptr != NULL && ptr[1] != '\0') {
				ptr++;
				int len = 64 + strlen(ptr);
				ptrarr[count]=new char[len]; sprintf(ptrarr[count],"All Messages from server %s",ptr);
				(ptrarr[count])[ strlen( ptrarr[count] ) - 1 ] = '\0'; // don't display the final '>' - though we still put this in the killfile
				b_mid = count;
				count++;
			}
		}
		{
			if(*message.dummyHeader != '\0') {
				int len = 64 + strlen(message.dummyHeader);
				ptrarr[count]=new char[len]; sprintf(ptrarr[count],"All Messages from NNTP posting host %s",message.dummyHeader);
				b_nph = count;
				count++;
			}
		}
		char * buttons[3];
		int nbuttons=0,cancel=0;
		if(*message.newsgroups != '\0' && strchr(message.newsgroups,',') == NULL) {
			// not a crosspost
			buttons[0]=new char[64]; strcpy(buttons[0],"Kill in all Newsgroups");
			buttons[1]=new char[64]; strcpy(buttons[1],"Kill in this Newsgroup");
			buttons[2]=new char[64]; strcpy(buttons[2],"Cancel");
			nbuttons=3;
			cancel=2;
		}
		else {
			// a crosspost
			buttons[0]=new char[64]; strcpy(buttons[0],"Kill in all Newsgroups");
			buttons[1]=new char[64]; strcpy(buttons[1],"Cancel");
			nbuttons=2;
			cancel=1;
		}
		Object * group = HGroup,
			Child, CY_wiz_EXPIREKILL=Cycle(CYA_acc_expirekill),
			Child, STR_wiz_EXPIREKILL=BetterStringObject, StringFrame, MUIA_String_Integer, account.defexpire, MUIA_String_MaxLen, 5, MUIA_String_Accept, "1234567890", MUIA_CycleChain, 1, End,
			End;
		DoMethod(CY_wiz_EXPIREKILL,MUIM_Notify,MUIA_Cycle_Active,0,
			STR_wiz_EXPIREKILL,3,MUIM_Set,MUIA_Disabled,TRUE);
		DoMethod(CY_wiz_EXPIREKILL,MUIM_Notify,MUIA_Cycle_Active,1,
			STR_wiz_EXPIREKILL,3,MUIM_Set,MUIA_Disabled,FALSE);
		DoMethod(CY_wiz_EXPIREKILL,MUIM_Notify,MUIA_Cycle_Active,2,
			STR_wiz_EXPIREKILL,3,MUIM_Set,MUIA_Disabled,FALSE);

		set(STR_wiz_EXPIREKILL,MUIA_Disabled,TRUE);
		set(CY_wiz_EXPIREKILL,MUIA_Cycle_Active,account.defexpiretype);
		ChoiceList * choice = new ChoiceList(app,wnd_main,"Kill",ptrarr,count,buttons,nbuttons,group);
		if(choice) {
			res=choice->show();
			sel=choice->getSelected();
			get(CY_wiz_EXPIREKILL,MUIA_Cycle_Active,&expiretype);
			char buffer[256]="";
			strcpy(buffer,getstr(STR_wiz_EXPIREKILL));
			expire = atoi(buffer);
			if(res==cancel || res==-1) {
				res=-1;
				sel=-1;
			}
		}
		if(choice)
			delete choice;
		MUI_DisposeObject(group);
		for(k=0;k<count;k++) {
			if(ptrarr[k])
				delete [] ptrarr[k];
		}
		for(k=0;k<nbuttons;k++) {
			if(buttons[k])
				delete buttons[k];
		}
	}
	else {
		sel = type % 4;
		res = type & 4;
		expiretype=0;
		expire=0;
	}
	KillFile * kill=new KillFile();
	switch (sel)
	{
	case 0:
		// by author
		strcpy(kill->header,"From:");
		strcpy(kill->text,message.from);
		break;
	case 1:
		// responses
		strcpy(kill->header,"References:");
		strcpy(kill->text,message.messageID);
		break;
	case 2:
		// subject
		strcpy(kill->header,"Subject:");
		strcpy(kill->text,message.subject);
		break;
	default:
		if(b_mid != -1 && sel == b_mid) {
			// server
			char *ptr = strchr(message.messageID,'@');
			if(ptr != NULL && ptr[1] != '\0') {
				ptr++;
				strcpy(kill->header,"Message-ID:");
				strcpy(kill->text,ptr);
			}
			else {
				delete kill;
				kill = NULL;
			}
		}
		else if(b_nph != -1 && sel == b_nph) {
			// NNTP posting host
			strcpy(kill->header,"NNTP-Posting-Host:");
			strcpy(kill->text,message.dummyHeader);
		}
		else {
			delete kill;
			kill = NULL;
		}
		break;
	}
	if(kill != NULL) {
		if(res==0)
			strcpy(kill->ngroups,"");
		else
			strcpy(kill->ngroups,message.newsgroups);
		kill->expiretype = expiretype;
		kill->expire = expire;
		account.defexpiretype = expiretype;
		account.defexpire = expire;
		// convert to upper case
		toUpper(kill->header);
		toUpper(kill->text);
		toUpper(kill->ngroups);
		DoMethod(NLIST_acc_KILLFILE,MUIM_NList_InsertSingle,kill,MUIV_NList_Insert_Bottom);
		save_killfile();
	}
	set(wnd_killfile,MUIA_Window_Sleep,FALSE);
}

void killmess(GroupData * gdata,MessageListData * mdata) {
	killmess(gdata,mdata,-1);
}

void exportAddress(GroupData * gdata,MessageListData * mdata) {
	nLog("exportAddress((GroupData *)%d,(MessageListData *)%d) called\n",gdata,mdata);
	char yamfile[300] = "YAM:.addressbook";
	char buffer[1024]="";
	strcpy(buffer,"copy >NIL: YAM:.addressbook YAM:.addressbook.bak");
	Execute(buffer,NULL,NULL);
	BPTR file = NULL;
	file=Open(yamfile,MODE_OLDFILE);
	if(file) {
		NewMessage * newmess = new NewMessage;
		get_refs(newmess,gdata,mdata,GETREFS_NONE);
		char name[256]="";
		char email[256]="";
		get_email(name,newmess->from,GETEMAIL_NAMEEMAIL);
		get_email(email,newmess->from,GETEMAIL_EMAIL);
		sprintf(buffer,"Enter the following into YAM's address book?:\nName : %s\nEmail : %s",name,email);
		LONG result=MUI_RequestA(app,0,0,"Export Address","_Yes|_Cancel",buffer,0);
		if(result==1) {
			Seek(file,0,OFFSET_END);
			Write(file,"\n",1);
			Write(file,"@USER ",6);
			Write(file,name,strlen(name));
			Write(file,"\n",1);
			Write(file,email,strlen(email));
			Write(file,"\n",1);
			Write(file,name,strlen(name));
			Write(file,"\n",1);
			Write(file,"\n\n\n\n\n\n",6);
			Write(file,"00000000\n\n\n",11);
			Write(file,"@ENDUSER",8);
		}
		Close(file);
		delete newmess;
	}
	else
		MUI_RequestA(app,0,0,"Export Address","_Okay","\33cCouldn't access file YAM:.addressbook",0);
	/*if(lock)
		UnLock(lock);*/
}

void resetArticlePointers(GroupData * gdata)
{
	nLog("resetArticlePointers((GroupData *)%d) called\n",gdata);
	gdata->flags[3]=0;
	gdata->flags[4]=0; // not really needed
	gdata->moreflags[3]=FALSE;
}

void resetArticlePointers() // do all groups
{
	nLog("resetArticlePointers() called\n");
	int entries;
	GroupData * gdata=NULL;
	getGdataEntries(&entries);
	for(int k=0;k<entries;k++) {
		getGdata(k,&gdata);
		if(gdata==NULL)
			continue;
		if(gdata->ID>=0)
			resetArticlePointers(gdata);
	}
}

void jumpto_unread()
{
	nLog("jumpto_unread() called\n");
	MUI_NListtree_TreeNode *tn;
	MUI_NListtree_TreeNode *temp_tn;
	MessageListData * mdata = NULL;
	int entries = 0;
	get(NLIST_messagelistdata,MUIA_NList_Entries,&entries);
	if(entries==0)
		return;
	if(account.mdata_view==0) {
		for(int k=0;k<entries;k++)
		{
			DoMethod(NLIST_messagelistdata,MUIM_NList_GetEntry,k,&mdata);
			if(mdata->flags[1])
			{
				setMdataActive(k);
				return;
			}
		}
	}
	else {
		tn=(MUI_NListtree_TreeNode *)DoMethod(LISTTREE_messagelistdata,MUIM_NListtree_GetEntry,MUIV_NListtree_GetEntry_ListNode_Root,MUIV_NListtree_GetEntry_Position_Head,0);
		for(int i=0; i<entries && tn!=NULL; i++) {
			mdata = (MessageListData *)tn->tn_User;
			if(mdata->flags[1]) {
				DoMethod(LISTTREE_messagelistdata,MUIM_NListtree_Open,MUIV_NListtree_Open_ListNode_Parent,tn,0);
				set(LISTTREE_messagelistdata,MUIA_NListtree_Active,tn);
				return;
			}
			temp_tn=(MUI_NListtree_TreeNode *)DoMethod(LISTTREE_messagelistdata,MUIM_NListtree_GetEntry,tn,MUIV_NListtree_GetEntry_Position_Head,0);
			if(temp_tn!=NULL) // we have child
				tn = temp_tn;
			else { // no child
				do {
					temp_tn=(MUI_NListtree_TreeNode *)DoMethod(LISTTREE_messagelistdata,MUIM_NListtree_GetEntry,tn,MUIV_NListtree_GetEntry_Position_Next,0);
					if(temp_tn!=NULL) // next in list
						break;
					// end of this list, go to parent then next
					tn=(MUI_NListtree_TreeNode *)DoMethod(LISTTREE_messagelistdata,MUIM_NListtree_GetEntry,tn,MUIV_NListtree_GetEntry_Position_Parent,0);
				} while(tn!=NULL);
				if(tn!=NULL)
					tn = temp_tn;
			}
		}
	}
	setMdataActive(0);
}

void correctDrawer(char *dest,char *src) {
	if(strchr(src,':')==NULL)
		sprintf(dest,"%s:",src);
	else {
		if(src[strlen(src)-1]==':' || src[strlen(src)-1]=='/')
			strcpy(dest,src);
		else
			sprintf(dest,"%s/",src);
	}
}

BOOL createDrawer(char * drawer) {
	char * p = drawer;
	char * p2 = NULL;
	BOOL success=TRUE;
	char buffer[300] = "";
	do {
		p2 = strchr(p,'/');
		if(p2==NULL)
			break;
		strncpy(buffer,drawer,(int)p2-(int)drawer); // don't include final '/'!
		buffer[(int)p2-(int)drawer]=0;
		if(!exists(buffer)) {
			// create this drawer
			BPTR lock = CreateDir(buffer);
			if(lock==NULL)
				return FALSE; // failed!
			UnLock(lock);
			lock=NULL;
		}
		p = p2+1;
	} while(*p != '\0');
	return TRUE;
}

void rot13(Object *ED) {
	int val = 0;
	get(ED,MUIA_TextEditor_AreaMarked,&val);
	if(val==FALSE)
		return;
	char *temp=(STRPTR)DoMethod(ED,MUIM_TextEditor_ExportText);
	if(temp) {
		int sx=0,sy=0,ex=0,ey=0;
		DoMethod(ED,MUIM_TextEditor_BlockInfo,&sx,&sy,&ex,&ey);
		int len=strlen(temp);
		if(ex<len && ey<len) {
			int cx=0,cy=0;
			char * cpos=temp;
			while(*cpos!=0) {
				if( (cy>sy && cy<ey) || (cy==sy && cx>=sx && sy!=ey) || (cy==ey && cx<ex && sy!=ey) || (sy==ey && cy==sy && cx>=sx && cx<ex) ) {
					if(*cpos >= 'a' && *cpos <= 'z') {
						*cpos -= 13;
						if(*cpos<'a')
							*cpos += 26;
					}
					else if(*cpos >= 'A' && *cpos <= 'Z') {
						*cpos -= 13;
						if(*cpos<'A')
							*cpos += 26;
					}
				}
				if(*cpos == '\n') {
					cx=0;
					cy++;
				}
				else
					cx++;
				cpos++;
			}
			set(ED,MUIA_TextEditor_Quiet,TRUE);
			DoMethod(ED,MUIM_TextEditor_ClearText);
			DoMethod(ED,MUIM_TextEditor_InsertText,temp,0);
			DoMethod(ED,MUIM_TextEditor_MarkText,sx,sy,ex,ey);
			set(ED,MUIA_TextEditor_Quiet,FALSE);
		}
		FreeVec(temp); // should be a FreeVec
	}
}

/*int do_input() {
	ULONG returnID = DoMethod(app,MUIM_Application_NewInput,&signal);
	if(returnID==0)
		return TRUE;
	else {
		nLog("do_input() detects returnID: %d\n",returnID);
	}*/
LONG returnID = NULL;
int do_input_func() {

	GroupData * gdata=NULL;
	MessageListData * mdata=NULL;;
	//char buffer[300]="";
	//char buffer2[300]="";
	char filename[1024] = "";
	char command[300]="";
	BPTR lock=NULL;
	int yesno = 0,entries = 0;
	STRPTR temp = NULL,temp2 = NULL;
	MessageListData **mdatalist=NULL;
	VOID *ptr = NULL,*ptr2 = NULL;
	switch(returnID) {
		case APP_DOUBLESTART:
			MUI_RequestA(app,0,0,"NewsCoaster","_Okay","\33cYou may not open more than one copy of\nNewsCoaster at a time!",0);
			break;
		case MEN_GETNEWS:
			if(delete_dis)
				MUI_RequestA(app,0,0,"Not Available","_Okay","\33cThis function not available whilst\nNewsCoaster is connected with a newsserver!",0);
			else
				getnews(-1);
			break;
		case MEN_GETNEWSSINGLE:
			if(delete_dis)
				MUI_RequestA(app,0,0,"Not Available","_Okay","\33cThis function not available whilst\nNewsCoaster is connected with a newsserver!",0);
			else {
				int val = 0;
				getGdataActivePos(&val);
				getGdataActive(&gdata);
				if(gdata==NULL)
					MUI_RequestA(app,0,0,"Fetch News","_Okay","\33cPlease select a newsgroup folder!",0);
				else if(gdata->ID >= 0)
					getnews(val);
				else
					MUI_RequestA(app,0,0,"Fetch News","_Okay","\33cPlease select a newsgroup folder!",0);
			}
			break;
		case MEN_SENDNEWS:
			if(delete_dis)
				MUI_RequestA(app,0,0,"Not Available","_Okay","\33cThis function not available whilst\nNewsCoaster is connected with a newsserver!",0);
			else
				postnews(0);
			break;
		case MEN_GETGROUPSDEF:
		case ACC_GETGROUPS:
		case GROUPMAN_GETGROUPS:
		{
			Server *server = NULL;
			if(returnID == ACC_GETGROUPS) {
				int val = 0;
				get(NLIST_acc_SERVERS,MUIA_NList_Active,&val);
				if(val!=MUIV_NList_Active_Off)
					DoMethod(NLIST_acc_SERVERS,MUIM_NList_GetEntry,val,&server);
			}
			else if(returnID == GROUPMAN_GETGROUPS)
				server = groupman_server;
			else
				server = getDefaultServer();
			if(server != NULL) {
				if(delete_dis)
					MUI_RequestA(app,0,0,"Not Available","_Okay","\33cThis function not available whilst\nNewsCoaster is connected with a newsserver!",0);
				else {
					sprintf(status_buffer_g,"\33cAre you sure you wish to download\nthe Groups list for %s?\n(It may take some time)",server->nntp);
					int result = MUI_RequestA(app,0,0,"Get Group List","_Yes|_Cancel",status_buffer_g,0);
					if(result==1) {
						result=getgrouplist(server);
						if(result!=-1) {
							int val = 0;
							get(wnd_groupman,MUIA_Window_Open,&val);
							if(val==FALSE) {
								sprintf(status_buffer_g,"\33c%d Groups found!\nGroup list has been downloaded into file \n%s.gl\nSelect Groups Manager from Program Settings to view list\n",result,server->nntp);
								MUI_RequestA(app,0,0,"Group List","_Okay",status_buffer_g,0);
							}
						}
					}
				}
			}
			break;
		}
		case MEN_GETNEWGROUPSDEF:
		case ACC_GETNEWGROUPS:
		{
			Server *server = NULL;
			if(returnID == ACC_GETNEWGROUPS) {
				int val = 0;
				get(NLIST_acc_SERVERS,MUIA_NList_Active,&val);
				if(val!=MUIV_NList_Active_Off)
					DoMethod(NLIST_acc_SERVERS,MUIM_NList_GetEntry,val,&server);
			}
			else
				server = getDefaultServer();
			if(server != NULL) {
				if(delete_dis)
					MUI_RequestA(app,0,0,"Not Available","_Okay","\33cThis function not available whilst\nNewsCoaster is connected with the newsserver!",0);
				else {
					getnewgroups(server);
				}
			}
			break;
		}
		case MEN_DISCONNECT:
			closeSockets();
			break;
		case MEN_USER:
			if(registered) {
				sprintf(status_buffer_g,"\33cThis copy of NewsCoaster is registered to:\33l\n%s.\n   ID:%d\nDate: %s\nThanks for registering :)",regist->Owner,regist->OwnerID,regist->Date);
				MUI_RequestA(app,0,0,newscoaster_name,"_Okay",status_buffer_g,0);
			}
			else
				MUI_RequestA(app,0,0,newscoaster_name,"_Okay","\33cUnregistered",0);
			break;
		case MEN_ABOUT:
			set(wnd_about,MUIA_Window_Open,TRUE);
			break;
		case MEN_ABOUTMUI:
			if(!aboutwin) {
				aboutwin = AboutmuiObject,
									MUIA_Aboutmui_Application,app,
									End;
			}
			if(aboutwin)
				set(aboutwin,MUIA_Window_Open,TRUE);
			else
				DisplayBeep(0);
			break;
		case MEN_SYSINFO:
		{
			set(wnd_main,MUIA_Window_Sleep,TRUE);
			char filename[] = "RAM:sysinfo.txt";
			DeleteFile(filename);
			printf("System Information\n");
			printf("------------------\n\n");
			
			BPTR file = Open(filename,MODE_NEWFILE);
			
			Execute("c:cpu",NULL,file);
			Execute("c:cpu",NULL,NULL);

			FPrintf(file,"\nCurrent Memory:\n"); Flush(file);
			printf("\nCurrent Memory:\n");
			Execute("c:avail",NULL,file);
			Execute("c:avail",NULL,NULL);

			FPrintf(file,"\nVersion Information:\n"); Flush(file);
			printf("\nVersion Information:\n");
			Execute("c:version",NULL,file);
			Execute("c:version",NULL,NULL);

			Execute("c:version NewsCoaster:NewsCoaster",NULL,file);
			Execute("c:version NewsCoaster:NewsCoaster",NULL,NULL);

			Execute("c:version libs:mui/BetterString.mcc",NULL,file);
			Execute("c:version libs:mui/BetterString.mcc",NULL,NULL);
			Execute("c:version libs:mui/BetterString.mcp",NULL,file);
			Execute("c:version libs:mui/BetterString.mcp",NULL,NULL);

			Execute("c:version libs:mui/NList.mcc",NULL,file);
			Execute("c:version libs:mui/NList.mcc",NULL,NULL);
			Execute("c:version libs:mui/NListview.mcc",NULL,file);
			Execute("c:version libs:mui/NListview.mcc",NULL,NULL);
			Execute("c:version libs:mui/NListviews.mcp",NULL,file);
			Execute("c:version libs:mui/NListviews.mcp",NULL,NULL);

			Execute("c:version libs:mui/TextEditor.mcc",NULL,file);
			Execute("c:version libs:mui/TextEditor.mcc",NULL,NULL);
			Execute("c:version libs:mui/TextEditor.mcp",NULL,file);
			Execute("c:version libs:mui/TextEditor.mcp",NULL,NULL);

			Execute("c:version libs:mui/NListtree.mcc",NULL,file);
			Execute("c:version libs:mui/NListtree.mcc",NULL,NULL);
			FPrintf(file,"NListtree.mcp "); Flush(file);
			printf("NListtree.mcp ");
			Execute("c:version libs:mui/NListtree.mcp",NULL,file);
			Execute("c:version libs:mui/NListtree.mcp",NULL,NULL);

			Execute("c:version libs:mui/Toolbar.mcc",NULL,file);
			Execute("c:version libs:mui/Toolbar.mcc",NULL,NULL);
			Execute("c:version libs:mui/Toolbar.mcp",NULL,file);
			Execute("c:version libs:mui/Toolbar.mcp",NULL,NULL);

			Close(file);

			printf("\nInformation saved to RAM:sysinfo.txt\n");
			MUI_RequestA(app,0,0,"System Information","_Okay","\33cSystem Information saved to\nRAM:sysinfo.txt",0);
			set(wnd_main,MUIA_Window_Sleep,FALSE);
			break;
		}
		case MEN_ICONIFY:
			set(app,MUIA_Application_Iconified,TRUE);
			break;
		case MUIV_Application_ReturnID_Quit:
		case MEN_QUIT:
		{
			int val = 0;
			get(app,MUIA_Application_ForceQuit,&val);
			int result = 0;
			if( val!=0 || (account.flags & Account::NOCONFIRMQUIT)!=0 )
				result = 1;
			else
				result = MUI_RequestA(app,0,0,"Quit Program","_Quit|_Cancel","\33cAre you sure you wish\nto Quit?",0);
			if(result==1) {
				WriteWindow **ptrs = (WriteWindow **)WriteWindow::ptrs->getData();
				int size = WriteWindow::ptrs->getSize();
				BOOL quit = TRUE;
				for(int i=0;i<size && quit;i++) {
					WriteWindow *ww = ptrs[i];
					//set(ww->wnd,MUIA_Window_Open,TRUE); // commented out, since it causes the Requester to immediately get moved to the back (even though we open the requester afterwards)?!
					int res = MUI_RequestA(app,ww->wnd,0,"Save Message","_Save|_Discard|_Cancel","\33cDo you wish to save the changes\nto this message?",0);
					if(res == 0)
						quit = FALSE;
					else if(res == 1)
						ww->save();
				}
				if(quit)
					running=FALSE;
			}
			break;
		}
		case MEN_NEWNEWSGROUP:
			/*if(delete_dis)
				MUI_RequestA(app,0,0,"Not Available","_Okay","\33cThis function not available whilst\nNewsCoaster is connected with the newsserver!",0);
			else*/
			{
			set(wnd_newnewsgroup,MUIA_Window_Open,TRUE);
			set(wnd_newnewsgroup,MUIA_Window_ActiveObject,STR_nng_NAME);
			nng_defserver = 0;
			}
			break;
		case MEN_EDITNG:
			/*if(delete_dis)
				MUI_RequestA(app,0,0,"Not Available","_Okay","\33cThis function not available whilst\nNewsCoaster is connected with the newsserver!",0);
			else*/
			{
			get(wnd_editng,MUIA_Window_Open,&yesno);
			if(!yesno) {
				getGdataActive(&gdata);
				if(gdata==NULL)
					MUI_RequestA(app,0,0,"Edit Newsgroup","_Okay","\33cPlease select a newsgroup to edit!",0);
				else if(gdata->ID>=0) {
					set(STR_eng_NAME,MUIA_String_Contents,gdata->name);
					set(STR_eng_DESC,MUIA_String_Contents,gdata->desc);
					set(CY_eng_DEFSIG,MUIA_Cycle_Active,gdata->defsig+1);
					if(gdata->max_dl==-1) {
						set(CY_eng_MAXDL,MUIA_Cycle_Active,0);
						set(STR_eng_MAXDL,MUIA_String_Integer,0);
					}
					else {
						set(CY_eng_MAXDL,MUIA_Cycle_Active,1);
						set(STR_eng_MAXDL,MUIA_String_Integer,gdata->max_dl);
					}
					if(gdata->flags[2]<=0) {
						set(CY_eng_MAXL,MUIA_Cycle_Active,0);
						set(STR_eng_MAXL,MUIA_String_Integer,1);
					}
					else {
						set(CY_eng_MAXL,MUIA_Cycle_Active,1);
						set(STR_eng_MAXL,MUIA_String_Integer,gdata->flags[2]);
					}
					set(CY_eng_MAXAGE,MUIA_Cycle_Active,gdata->flags[6]);
					set(STR_eng_MAXAGE,MUIA_String_Integer,gdata->flags[7]);
					set(CY_eng_OFFLINE,MUIA_Cycle_Active,gdata->flags[5]);
					DateHandler::get_date(status_buffer_g,getGMTOffset(),account.bst,gdata->lastdlds);
					set(TXT_eng_LASTDL,MUIA_Text_Contents,status_buffer_g);
					if(gdata->ID==-1)
						strcpy(status_buffer_g,"outgoing/");
					else if(gdata->ID==-2)
						strcpy(status_buffer_g,"sent/");
					else if(gdata->ID==-3)
						strcpy(status_buffer_g,"deleted/");
					else
						sprintf(status_buffer_g,"folder_%d/",gdata->ID);
					set(TXT_eng_FOLDER,MUIA_Text_Contents,status_buffer_g);
					set(CM_eng_S,MUIA_Selected,gdata->s);
					set(wnd_editng,MUIA_Window_Open,TRUE);
					if(DoMethod(GROUP_eng,MUIM_Group_InitChange))
						DoMethod(GROUP_eng,MUIM_Group_ExitChange);
					set(wnd_editng,MUIA_Window_ActiveObject,STR_eng_NAME);
					ng_edit=gdata;
				}
				else
					MUI_RequestA(app,0,0,"Edit Newsgroup","_Okay","\33cPlease select a newsgroup to edit!",0);
			}
			else {
				MUI_RequestA(app,0,0,"Edit Newsgroup","_Okay","\33cPlease finish editing current group.",0);
				set(wnd_editng,MUIA_Window_Open,TRUE);
			}
			}
			break;
		case MEN_NGADV:
			/*if(delete_dis)
				MUI_RequestA(app,0,0,"Not Available","_Okay","\33cThis function not available whilst\nNewsCoaster is connected with the newsserver!",0);
			else*/
			{
			get(wnd_ngadv,MUIA_Window_Open,&yesno);
			if(!yesno) {
				getGdataActive(&gdata);
				if(gdata==NULL)
					MUI_RequestA(app,0,0,"Newsgroup Advanced Settings","_Okay","\33cPlease select a newsgroup to edit!",0);
				else if(gdata->ID>=0) {
					set(CM_ngadv_APPVHD,MUIA_Selected,gdata->moreflags[0]);
					set(STR_ngadv_APPVHD,MUIA_String_Contents,gdata->appv_hd);
					set(CM_ngadv_ALTNAME,MUIA_Selected,gdata->moreflags[1]);
					set(STR_ngadv_ALTNAME,MUIA_String_Contents,gdata->alt_name);
					set(CM_ngadv_ALTEMAIL,MUIA_Selected,gdata->moreflags[2]);
					set(STR_ngadv_ALTEMAIL,MUIA_String_Contents,gdata->alt_email);
					freeServerCycle();
					int active=setServerCycle(gdata->serverID);
					set(CM_ngadv_SERVERPOST,MUIA_Selected,gdata->moreflags[4]);

					ng_editadv=gdata;
					set(wnd_ngadv,MUIA_Window_Open,TRUE);
					set(CY_ngadv_SERVER,MUIA_Cycle_Active,active);
				}
				else
					MUI_RequestA(app,0,0,"Newsgroup Advanced Settings","_Okay","\33cPlease select a newsgroup to edit!",0);
			}
			else {
				MUI_RequestA(app,0,0,"Newsgroup Advanced Settings","_Okay","\33cPlease finish editing current group.",0);
				set(wnd_ngadv,MUIA_Window_Open,TRUE);
			}
			}
			break;
		case MEN_DELNG:
			if(delete_dis)
				MUI_RequestA(app,0,0,"Not Available","_Okay","\33cThis function not available whilst\nNewsCoaster is connected with the newsserver!",0);
			else {
				getGdataActive(&gdata);
				if(gdata==NULL)
					MUI_RequestA(app,0,0,"Delete Newsgroup","_Okay","\33cPlease select a newsgroup!",0);
				else if(gdata->ID>=0) {
					int result = MUI_RequestA(app,0,0,"Delete Newsgroup","Delete|_Cancel","\33cAre you *sure* you wish\nto Delete this Newsgroup?",0);
					if(result==1) {
						set(wnd_main,MUIA_Window_Sleep,TRUE);
						sprintf(command,"delete NewsCoasterData:Folder_%d/ all >NIL:",gdata->ID);
						Execute(command,NULL,NULL);
						removeGdataActive();
						set(wnd_main,MUIA_Window_Sleep,FALSE);
						account.save_data();
					}
				}
				else
					MUI_RequestA(app,0,0,"Delete Newsgroup","_Okay","\33cYou may not delete this folder!",0);
			}
			break;
		case MEN_ARCHIVENG:
			if(delete_dis)
				MUI_RequestA(app,0,0,"Not Available","_Okay","\33cThis function not available whilst\nNewsCoaster is connected with the newsserver!",0);
			else {
				getGdataActive(&gdata);
				if(gdata==NULL)
					MUI_RequestA(app,0,0,"Archive Newsgroup","_Okay","\33cPlease select a newsgroup!",0);
				else {
					sprintf(status_buffer_g,"%s.mbx",gdata->name);
					sleepAll(TRUE);
					char *filename = new char[1024];
					BOOL ok = LoadASL(filename,"File to save archive as...",status_buffer_g,"#?",FALSE);
					sleepAll(FALSE);
					if(ok)
						archiveGroup(gdata,filename);
					delete [] filename;
				}
			}
			break;
		case MEN_VIEWGROUPSLIST:
			if(account.grouplistType!=0) {
				account.save_data(); // also needed to save out current grouplist
				account.grouplistType=0;
				readInGroups();
				set(wnd_main,MUIA_Window_Open,FALSE);
				DoMethod(grouplistGroup,OM_REMMEMBER,grouplistGroup_LISTTREE);
				DoMethod(grouplistGroup,OM_ADDMEMBER,grouplistGroup_NLIST);
				set(wnd_main,MUIA_Window_Open,TRUE);
				DoMethod(menuitem_VIEWGROUPS,MUIM_SetUData,MEN_VIEWGROUPSLIST,MUIA_Menuitem_Checked,account.grouplistType==0);
				DoMethod(menuitem_VIEWGROUPS,MUIM_SetUData,MEN_VIEWGROUPSTREE,MUIA_Menuitem_Checked,account.grouplistType==1);
				account.save_data(); //now save changed view type
				resetGdataActive();
			}
			break;
		case MEN_VIEWGROUPSTREE:
			if(account.grouplistType!=1 && nlisttree==TRUE) {
				account.save_data(); // also needed to save out current grouplist
				account.grouplistType=1;
				readInGroups();
				set(wnd_main,MUIA_Window_Open,FALSE);
				DoMethod(grouplistGroup,OM_REMMEMBER,grouplistGroup_NLIST);
				DoMethod(grouplistGroup,OM_ADDMEMBER,grouplistGroup_LISTTREE);
				set(wnd_main,MUIA_Window_Open,TRUE);
				DoMethod(menuitem_VIEWGROUPS,MUIM_SetUData,MEN_VIEWGROUPSLIST,MUIA_Menuitem_Checked,account.grouplistType==0);
				DoMethod(menuitem_VIEWGROUPS,MUIM_SetUData,MEN_VIEWGROUPSTREE,MUIA_Menuitem_Checked,account.grouplistType==1);
				account.save_data(); //now save changed view type
				resetGdataActive();
			}
			break;
		case MEN_SORT:
		{
			int result = MUI_RequestA(app,0,0,"Sort Newsgroup","_Sort|_Cancel","\33cAre you sure you wish to\nsort the newsgroups list alphabetically?\n(Current ordering will be lost!)",0);
			if(result==1) {
				if(account.grouplistType==0)
					DoMethod(NLIST_groupdata,MUIM_NList_Sort);
				account.save_data();
			}
			break;
		}
		case MEN_SEARCH:
		{
			getGdataEntries(&entries);
			DoMethod(NLIST_search_NG,MUIM_NList_Clear);
			for(int k=0;k<entries;k++) {
				GroupData *gdata = NULL;
				getGdata(k,&gdata);
				if(gdata==NULL)
					continue;
				// make a copy!
				/*ptr2=new char[256];
				strcpy((char *)ptr2,((GroupData *)ptr)->name);
				DoMethod(NLIST_search_NG,MUIM_NList_InsertSingle,ptr2,MUIV_NList_Insert_Bottom);*/
				GroupData *gdata_c = new GroupData();
				*gdata_c = *gdata;
				DoMethod(NLIST_search_NG,MUIM_NList_InsertSingle,gdata_c,MUIV_NList_Insert_Bottom);
			}
			set(wnd_search,MUIA_Window_Open,TRUE);
			break;
		}
		case MEN_STATS:
		{
			getGdataEntries(&entries);
			DoMethod(NLIST_stats_NG,MUIM_NList_Clear);
			for(int k=0;k<entries;k++) {
				GroupData *hdata = NULL;
				getGdata(k,&gdata);
				if(gdata==NULL)
					continue;
				// make a copy!
				/*ptr2=new char[256];
				strcpy((char *)ptr2,((GroupData *)ptr)->name);
				DoMethod(NLIST_stats_NG,MUIM_NList_InsertSingle,(GroupData *)ptr2,MUIV_NList_Insert_Bottom);*/
				GroupData *gdata_c = new GroupData();
				*gdata_c = *gdata;
				DoMethod(NLIST_stats_NG,MUIM_NList_InsertSingle,gdata_c,MUIV_NList_Insert_Bottom);
			}
			set(wnd_stats,MUIA_Window_Open,TRUE);
			break;
		}
		case MEN_RESETGROUPPTR:
			getGdataActive(&gdata);
			if(gdata==NULL)
				MUI_RequestA(app,0,0,"Reset Article Pointer","_Okay","\33cPlease select a newsgroup!",0);
			else if(gdata->ID>=0) {
				int result = MUI_RequestA(app,0,0,"Reset Article Pointer","_Reset|_Cancel","\33cReset the article pointer for this newsgroup\n - as if you had just created this newsgroup folder\n(see documentation for details).",0);
				if(result==1)
					resetArticlePointers(gdata);
			}
			else
				MUI_RequestA(app,0,0,"Reset Article Pointer","_Okay","\33cPlease select a newsgroup!",0);
			break;
		case MEN_RESETALLPTR:
		{
			int result = MUI_RequestA(app,0,0,"Reset Article Pointers","Reset|_Cancel","\33cReset the article pointer for all newsgroups\n - as if you had just created the newsgroup folders\n(see documentation for details).",0);
			if(result==1)
				resetArticlePointers();
			break;
		}
		case MEN_GROUPMANDEF:
		case ACC_GROUPMAN:
		{
			Server *server = NULL;
			if(returnID == ACC_GROUPMAN) {
				int val = 0;
				get(NLIST_acc_SERVERS,MUIA_NList_Active,&val);
				if(val!=MUIV_NList_Active_Off) {
					DoMethod(NLIST_acc_SERVERS,MUIM_NList_GetEntry,val,&server);
					//printf(":::%s\n",server->nntp);
				}
			}
			else
				server = getDefaultServer();
			if(server != NULL) {
				get(wnd_groupman,MUIA_Window_Open,&yesno);
				if(!yesno) {
					int result = MUI_RequestA(app,0,0,"Group Manager","_Yes|_Cancel","\33cAre you sure you wish to open\nthe Group Manager window?\n(It takes a little time to read in\nall the groups)",0);
					if(result==1) {
						groupman_server = server;
						readgrouplist(groupman_server,0);
						set(wnd_groupman,MUIA_Window_Open,TRUE);
					}
				}
				else
					set(wnd_groupman,MUIA_Window_Open,TRUE);
			}
			break;
		}
		case MEN_UPDATEGROUPS:
			if(delete_dis)
				MUI_RequestA(app,0,0,"Not Available","_Okay","\33cThis function not available whilst\nNewsCoaster is connected with the newsserver!",0);
			else {
				int result = MUI_RequestA(app,0,0,"Update Groups","_Update|_Cancel","\33cAre you sure you wish\nto Update the Newsgroup List?\n(Settings may be lost)",0);
				if(result==1)
					update_groups();
			}
			break;
		case MEN_UPDATEINDEX:
			if(delete_dis)
				MUI_RequestA(app,0,0,"Not Available","_Okay","\33cThis function not available whilst\nNewsCoaster is connected with the newsserver!",0);
			else {
				int result = MUI_RequestA(app,0,0,"Update Index","_Update|_Cancel","\33cAre you sure you wish\nto Update the index for this Group?\n",0);
				if(result==1) {
					getGdataActive(&gdata);
					if(gdata==NULL)
						MUI_RequestA(app,0,0,"Update Index","_Okay","\33cPlease select a newsgroup!",0);
					else
						update_index();
				}
			}
			break;
		case MEN_UPDATEALLIND:
			if(delete_dis)
				MUI_RequestA(app,0,0,"Not Available","_Okay","\33cThis function not available whilst\nNewsCoaster is connected with the newsserver!",0);
			else {
				int result = MUI_RequestA(app,0,0,"Update Indices","_Update|_Cancel","\33cAre you sure you wish\nto Update all the Group indices?\n(Will take a little time.)",0);
				if(result==1) {
					getGdataEntries(&entries);
					for(int k=0;k<entries;k++) {
						getGdata(k,&gdata);
						if(gdata==NULL)
							continue;
						set_gdata(gdata);
						if(update_index())
							break;
					}
				}
			}
			break;
		case MEN_IMPORT:
			if(delete_dis)
				MUI_RequestA(app,0,0,"Not Available","_Okay","\33cThis function not available whilst\nNewsCoaster is connected with the newsserver!",0);
			else
				import();
			break;
		case MEN_VIEWMESSAGESLIST:
			if(account.mdata_view!=0) {
				MessageListData * current_mdata = NULL;
				getMdataActive(&current_mdata);
				//printf("%d\n",current_mdata);
				//if(current_mdata != NULL && get_mdataptr_pos(current_mdata) == -1)
				//	current_mdata = NULL; // message no longer exists in list - we don't want to reference it, in cases it's been deleted!

				account.save_data(); // also needed to save out current grouplist
				account.mdata_view=0;
				set(wnd_main,MUIA_Window_Open,FALSE);
				DoMethod(messageGroup,OM_REMMEMBER,messageGroup_LISTTREE);
				DoMethod(messageGroup,OM_ADDMEMBER,messageGroup_NLIST);
				set(wnd_main,MUIA_Window_Open,TRUE);
				DoMethod(menuitem_VIEWMESSAGES,MUIM_SetUData,MEN_VIEWMESSAGESLIST,MUIA_Menuitem_Checked,account.mdata_view==0);
				DoMethod(menuitem_VIEWMESSAGES,MUIM_SetUData,MEN_VIEWMESSAGESTREE,MUIA_Menuitem_Checked,account.mdata_view==1);
				account.save_data(); //now save changed view type

				if(current_mdata != NULL) {
					//printf("-->%d : %s\n",current_mdata->ID,current_mdata->subject);
					set_mdata(current_mdata);
				}
			}
			break;
		case MEN_VIEWMESSAGESTREE:
			if(account.mdata_view!=1 && nlisttree==TRUE) {
				MessageListData * current_mdata = NULL;
				getMdataActive(&current_mdata);
				//printf("%d\n",current_mdata);
				//if(current_mdata != NULL && get_mdataptr_pos(current_mdata) == -1)
				//	current_mdata = NULL; // message no longer exists in list - we don't want to reference it, in cases it's been deleted!

				account.save_data(); // also needed to save out current grouplist
				account.mdata_view=1;
				threadView();

				set(wnd_main,MUIA_Window_Open,FALSE);
				DoMethod(messageGroup,OM_REMMEMBER,messageGroup_NLIST);
				DoMethod(messageGroup,OM_ADDMEMBER,messageGroup_LISTTREE);
				set(wnd_main,MUIA_Window_Open,TRUE);
				DoMethod(menuitem_VIEWMESSAGES,MUIM_SetUData,MEN_VIEWMESSAGESLIST,MUIA_Menuitem_Checked,account.mdata_view==0);
				DoMethod(menuitem_VIEWMESSAGES,MUIM_SetUData,MEN_VIEWMESSAGESTREE,MUIA_Menuitem_Checked,account.mdata_view==1);
				account.save_data(); //now save changed view type

				if(current_mdata != NULL) {
					//printf("-->%d : %s\n",current_mdata->ID,current_mdata->subject);
					set_mdata(current_mdata);
				}
			}
			break;
		case MEN_READ:
		{
			int result = 0;
			getMdataActivePos(&result);
			if(result!=MUIV_NList_Active_Off) {
				ViewWindow *vw;
				if(ViewWindow::ptrs->getSize()==0 || account.multiplevws==TRUE)
					vw = new ViewWindow("NewsCoaster");
				else {
					vw = ((ViewWindow **)ViewWindow::ptrs->getData())[0];
					vw->reset();
				}
				set(wnd_main,MUIA_Window_Sleep,TRUE);
				if(!vw->read())
					delete vw;
				set(wnd_main,MUIA_Window_Sleep,FALSE);
			}
			else
				MUI_RequestA(app,0,0,"Read Message","_Okay","\33cPlease select a message!",0);
			break;
		}
		case MEN_EDIT:
			/*get(wnd_write,MUIA_Window_Open,&yesno);
			if(!yesno)*/
			{
				int result = 0;
				getMdataActivePos(&result);
				if(result!=MUIV_NList_Active_Off) {
					getGdataDisplayed(&gdata);
					if(gdata->ID<0) {
						getMdataActive(&mdata);
						// search currently edited messages
						WriteWindow **data = (WriteWindow **)WriteWindow::ptrs->getData();
						int size = WriteWindow::ptrs->getSize();
						WriteWindow *ww = NULL;
						for(int i=0;i<size;i++) {
							if(data[i]->newmessage.edit && stricmp(data[i]->newmessage.messageID,mdata->messageID)==0) {
								ww = data[i];
								break;
							}
						}
						if(ww == NULL)
							WriteWindow::editMess(gdata,mdata,FALSE);
						else {
							set(ww->wnd,MUIA_Window_Open,TRUE);
						}
					}
					else
						MUI_RequestA(app,0,0,"Edit Message","_Okay","\33cYou can only edit your own messages!\n(Those in 'Outgoing' or 'Sent')",0);
				}
				else
					MUI_RequestA(app,0,0,"Edit Message","_Okay","\33cYou must first select a message to edit!",0);
			}
			/*else
				MUI_RequestA(app,0,0,"Edit Message","_Okay","\33cYou may only write one message\nat a time.\nPlease finish/cancel the\nexisting message.",0);*/
			break;
		case MEN_SUPER:
			/*get(wnd_write,MUIA_Window_Open,&yesno);
			if(!yesno)*/
			{
				int result = 0;
				getMdataActivePos(&result);
				if(result!=MUIV_NList_Active_Off) {
					getGdataDisplayed(&gdata);
					if(gdata->ID==-2) {
						getMdataActive(&mdata);
						WriteWindow::editMess(gdata,mdata,TRUE);
					}
					else
						MUI_RequestA(app,0,0,"Supersede Message","_Okay","\33cYou can only supersede messages you have sent!",0);
				}
				else
					MUI_RequestA(app,0,0,"Supersede Message","_Okay","\33cYou must first select a message to supersede!",0);
			}
			/*else
				MUI_RequestA(app,0,0,"Supersede Message","_Okay","\33cYou may only write one message\nat a time.\nPlease finish/cancel the\nexisting message.",0);*/
			break;
		case MEN_CANCEL:
			//get(wnd_write,MUIA_Window_Open,&yesno);
			//if(!yesno)
			{
				int result = 0;
				getMdataActivePos(&result);
				if(result!=MUIV_NList_Active_Off) {
					getGdataDisplayed(&gdata);
					if(gdata->ID==-2) {
						int result = MUI_RequestA(app,0,0,"Cancel Message","Cancel _Message|Don't Cancel","\33cAre you sure you wish\nto Cancel this message?\n",0);
						if(result==1) {
							getMdataActive(&mdata);
							WriteWindow::cancelMess(mdata);
							MUI_RequestA(app,0,0,"Cancel Message","_Okay","\33cCancel message placed in queue;\nSend News to cancel your message on the newsserver.\n",0);
						}
					}
					else
						MUI_RequestA(app,0,0,"Cancel Message","_Okay","\33cYou can only supersede messages you have sent!",0);
				}
				else
					MUI_RequestA(app,0,0,"Cancel Message","_Okay","\33cYou must first select a message to supersede!",0);
			}
			break;
		case MEN_DELMESS:
			/*if(delete_dis)
				MUI_RequestA(app,0,0,"Not Available","_Okay","\33cThis function not available whilst\nNewsCoaster is connected with the newsserver!",0);
			else*/
			delete_multi(TRUE);
			break;
		case MEN_UNDELMESS:
			getGdataDisplayed(&gdata);
			if(gdata->ID==-3)
				undelete_multi(TRUE);
			break;
		case MEN_PDTHIS:
		{
			int result = MUI_RequestA(app,0,0,"Delete Message(s)","_Delete|_Cancel","\33cAre you *sure* you wish\nto Delete the selected Message(s)?\nWARNING - These messages will be deleted immediately, and not\ncopied to the 'deleted folder'!",0);
			if(result==1)
				delete_multi(FALSE,FALSE); // permanent delete
			break;
		}
		case MEN_PDREAD:
		{
			int result = MUI_RequestA(app,0,0,"Delete Read Messages","_Delete|_Cancel","\33cThis option will remove all read messages\nin this newsgroup.\nWARNING - These messages will be deleted immediately, and not\ncopied to the 'deleted folder'!",0);
			if(result==1) {
				get(NLIST_messagelistdata,MUIA_NList_Entries,&entries);
				getGdataDisplayed(&gdata);
				setMdataQuiet(TRUE);
				set(wnd_main,MUIA_Window_Sleep,TRUE);
				MessageListData ** mdatalist = new MessageListData *[entries];
				int l=0;
				for(int k=0;k<entries;k++) {
					//getMdataVisible(k,&mdata);
					DoMethod(NLIST_messagelistdata,MUIM_NList_GetEntry,k,&mdata);
					if(!mdata->flags[1]) {
							//mdatalist[l] = new MessageListData();
							//*mdatalist[l++]=*mdata;
							mdatalist[l++] = mdata;
					}
				}
				if(l>0) {
					for(k=0;k<l;k++) {
						delete_mess(gdata,mdatalist[k],FALSE);
					}
					threadView();
				}
				if(mdatalist) {
					delete [] mdatalist;
					mdatalist=NULL;
				}
				setEnabled();
				redrawGdataAll();
				set(wnd_main,MUIA_Window_Sleep,FALSE);
				setMdataQuiet(FALSE);
			}
			break;
		}
		case MEN_PDONLINE:
		{
			int result = MUI_RequestA(app,0,0,"Delete Headers","_Delete|_Cancel","\33cThis option will remove all headers\nthat have not been entirely downloaded. ",0);
			if(result==1) {
				get(NLIST_messagelistdata,MUIA_NList_Entries,&entries);
				getGdataDisplayed(&gdata);
				setMdataQuiet(TRUE);
				set(wnd_main,MUIA_Window_Sleep,TRUE);
				MessageListData ** mdatalist = new MessageListData *[entries];
				int l=0;
				for(int k=0;k<entries;k++) {
					//getMdataVisible(k,&mdata);
					DoMethod(NLIST_messagelistdata,MUIM_NList_GetEntry,k,&mdata);
					if(mdata->flags[12]) {
							//mdatalist[l] = new MessageListData();
							//*mdatalist[l++]=*mdata;
							mdatalist[l++] = mdata;
					}
				}
				if(l>0) {
					//clearThreadView();
					for(k=0;k<l;k++)
						delete_mess(gdata,mdatalist[k],FALSE);
					threadView();
				}
				if(mdatalist) {
					delete [] mdatalist;
					mdatalist=NULL;
				}
				setEnabled();
				redrawGdataAll();
				set(wnd_main,MUIA_Window_Sleep,FALSE);
				setMdataQuiet(FALSE);
			}
			break;
		}
		case MEN_PDDUP:
		{
			int result = MUI_RequestA(app,0,0,"Delete Duplicates","_Delete|_Cancel","\33cThis option will remove all duplicated messages\nin this folder. ",0);
			if(result==1) {
				get(NLIST_messagelistdata,MUIA_NList_Entries,&entries);
				getGdataDisplayed(&gdata);
				setMdataQuiet(TRUE);
				set(wnd_main,MUIA_Window_Sleep,TRUE);
				MessageListData **mdatalist = new MessageListData *[entries];
				MessageListData **store = new MessageListData *[entries];
				int n_store = 0;
				BOOL *del = new BOOL[entries];
				for(int k=0;k<entries;k++) {
					del[k] = FALSE;
				}
				int l=0;
				for(k=0;k<entries;k++) {
					if(del[k]) {
						// will already delete
						continue;
					}
					DoMethod(NLIST_messagelistdata,MUIM_NList_GetEntry,k,&mdata);
					store[n_store++] = mdata;
					// now find if duplicates
					for(int j=0;j<entries;j++) {
						if( del[j] || j==k)
							continue;

						MessageListData *mdata2 = NULL;
						DoMethod(NLIST_messagelistdata,MUIM_NList_GetEntry,j,&mdata2);
						if( strcmp(mdata->messageID,mdata2->messageID)==0 ) {
							// duplicate!
							store[n_store++] = mdata2;
							del[j] = TRUE;
							//mdatalist[l++] = mdata2;
						}
					}

					// store is now an array of duplicates - so keep the 'best' one, and discard the rest
					if(n_store > 1) {
						int keep = 0;
						int j=0;
						for(j=1;j<n_store;j++) {
							//printf("%d : %d\n",j,store[j]->flags[12]);
							if( !store[j]->flags[12] ) {
								// offline message
								keep = j;
								//printf("set keep to %d\n",keep);
								break;
							}
						}
						// are any marked as read?
						for(j=0;j<n_store;j++) {
							if( !store[j]->flags[1] ) {
								// mark the kept one as read
								store[keep]->flags[1] = FALSE;
								break;
							}
						}

						//printf("keep = %d\n\n",keep);
						for(j=0;j<n_store;j++) {
							if(j != keep) {
								mdatalist[l++] = store[j];
							}
						}
					}
					n_store = 0;
				}
				if(l>0) {
					for(k=0;k<l;k++) {
						//printf("del: %s\n",mdatalist[k]->subject);
						delete_mess(gdata,mdatalist[k],FALSE);
					}
					threadView();
				}
				if(mdatalist) {
					delete [] mdatalist;
					mdatalist = NULL;
				}
				if(store) {
					delete [] store;
					store = NULL;
				}
				if(del) {
					delete [] del;
					del = NULL;
				}
				setEnabled();
				redrawGdataAll();
				set(wnd_main,MUIA_Window_Sleep,FALSE);
				setMdataQuiet(FALSE);
			}
			break;
		}
		case MEN_PDALL:
		{
			int result = MUI_RequestA(app,0,0,"Delete Message(s)","Delete|_Cancel","\33cAre you *sure* you wish\nto Delete all the Messages in this folder?\nWARNING - These messages will be deleted immediately, and not\ncopied to the 'deleted folder'!",0);
			if(result==1) {
				set(wnd_main,MUIA_Window_Sleep,TRUE);
				setMdataQuiet(TRUE);
				deleteFolderContents();
				redrawGdataAll();
				setMdataQuiet(FALSE);
				set(wnd_main,MUIA_Window_Sleep,FALSE);
			}
			break;
		}
		case MEN_PDALLALL:
		{
			int result = MUI_RequestA(app,0,0,"Delete Message(s)","Delete|_Cancel","\33cAre you *sure* you wish\nto Delete ALL the Messages in ALL newsgroups?\n(This does not include outgoing or sent)\nWARNING - These messages will be deleted immediately, and not\ncopied to the 'deleted folder'!",0);
			if(result==1) {
				result=MUI_RequestA(app,0,0,"Delete Message(s)","Yes I'm Sure|_Cancel","\33cAre you absolutely sure you wish\nto Delete ALL the Messages in ALL newsgroups?\n(Last chance)\n(This does not include outgoing or sent)",0);
				if(result==1) {
					getGdataEntries(&entries);
					set(wnd_main,MUIA_Window_Sleep,TRUE);
					for(int k=0;k<entries;k++) {
						getGdata(k,&gdata);
						if(gdata==NULL)
							continue;
						if(gdata->ID>=0)
							deleteFolderContents(gdata);
					}
					redrawGdataAll();
					set(wnd_main,MUIA_Window_Sleep,FALSE);
				}
			}
			break;
		}
		case MEN_POST:
			/*get(wnd_write,MUIA_Window_Open,&yesno);
			if(!yesno)*/
			{
				WriteWindow *ww = new WriteWindow("NewsCoaster (composing message)");
				getGdataDisplayed(&gdata);
				if(gdata->ID>=0) {
					strcpy(status_buffer_g,gdata->name);
					set(ww->STR_write_NG,MUIA_String_Contents,status_buffer_g);
					set(ww->CY_write_SIG,MUIA_Cycle_Active,gdata->defsig+1);
				}
				else {
					set(ww->STR_write_NG,MUIA_String_Contents,"");
					set(ww->CY_write_SIG,MUIA_Cycle_Active,1);
				}
				set(ww->ED_write_MESS,MUIA_TextEditor_CursorY,0);
				getUserEmail(gdata,status_buffer_g);
				set(ww->STR_write_FROM,MUIA_String_Contents,status_buffer_g);
				set(ww->wnd,MUIA_Window_Open,TRUE);
				set(ww->wnd,MUIA_Window_ActiveObject,ww->ED_write_MESS);
				/*if( gdata->defsig >= 0 && gdata->ID >= 0
						//&& account.usesig==TRUE
					) {
					strcpy(status_buffer_g,"-- \n");
					DoMethod(ww->ED_write_MESS,MUIM_TextEditor_InsertText,status_buffer_g,MUIV_TextEditor_InsertText_Bottom);
					if(sigs[gdata->defsig])
						DoMethod(ww->ED_write_MESS,MUIM_TextEditor_InsertText,sigs[gdata->defsig],MUIV_TextEditor_InsertText_Bottom);
				}*/
				ww->newmessage.nrefs=0;
				ww->newmessage.edit=FALSE;
				ww->newmessage.reply=FALSE;
				strcpy(ww->newmessage.messageID,"");
				strcpy(ww->newmessage.supersedeID,"");
				DoMethod(ww->NLIST_write_ATT,MUIM_NList_Clear);
			}
			break;
		case MEN_FOLLOWUP:
			WriteWindow::reply(TRUE,FALSE);
			break;
		case MEN_REPLY:
			WriteWindow::reply(FALSE,TRUE);
			break;
		case MEN_BOTH:
			WriteWindow::reply(TRUE,TRUE);
			break;
		case MEN_EXP:
		{
			getGdataDisplayed(&gdata);
			int result = 0;
			getMdataActivePos(&result);
			if(result!=MUIV_NList_Active_Off) {
				getMdataActive(&mdata);
				ViewWindow *vw = ViewWindow::createExportWindow(app,"NewsCoaster",gdata->ID,mdata->ID);
				set(wnd_main,MUIA_Window_Sleep,TRUE);
				if(!vw->read())
					delete vw;
				set(wnd_main,MUIA_Window_Sleep,FALSE);
			}
			else
				MUI_RequestA(app,0,0,"Export Message","_Okay","\33cPlease select a message.",0);
			break;
		}
		case MEN_VIEWHEADER:
		{
			getGdataDisplayed(&gdata);
			int result = 0;
			getMdataActivePos(&result);
			if(result!=MUIV_NList_Active_Off) {
				getMdataActive(&mdata);
				set(wnd_main,MUIA_Window_Sleep,TRUE);
				char filenamenew[256] = "";
				//char line[MAXLINE] = "";
				char *line = new char[MAXLINE + 1];
				getFilePath(filename,gdata->ID,mdata->ID);
				sprintf(filenamenew,"NewsCoasterData:nc_tempfile%d",rand() % 65536);
				//sprintf(newfilename,"RAM:nc_tempfile%d",rand() % 65536);
				BPTR lock = Lock(filename,ACCESS_READ);
				BPTR file = Open(filename,MODE_OLDFILE);
				BPTR newfile = NULL;
				if(file != NULL)
					newfile = Open(filenamenew,MODE_NEWFILE);
				if(file != NULL && newfile != NULL) {
					for(;;) {
						if(!FGets(file,line,MAXLINE))
							break;
						if(*line=='\n' || *line=='\r')
							break;
						if(strncmp(line,"X-NewsCoaster",13)==0)
							continue; // don't show this line
						Write(newfile,line,strlen(line));
					}
				}
				if(newfile != NULL)
					Close(newfile);
				if(file != NULL)
					Close(file);
				if(lock != NULL)
					UnLock(lock);
				set(wnd_main,MUIA_Window_Sleep,FALSE);
				if(newfile != NULL) {
					if(*account.defviewer==0)
						sprintf(command,"run >NIL: sys:utilities/multiview \"%s\"",filenamenew);
					else {
						sprintf(status_buffer_g,"run >NIL: %s",account.defviewer);
						sprintf(command,status_buffer_g,filenamenew);
					}
					for(int k=0;k<account.mimeprefsno;k++) {
						if(strstr("text/plain",account.mimeprefs[k]->type)!=NULL) {
							sprintf(status_buffer_g,"run >NIL: %s",account.mimeprefs[k]->viewer);
							sprintf(command,status_buffer_g,filename);
						}
					}
					Execute(command,NULL,NULL);
				}
				delete [] line;
			}
			else
				MUI_RequestA(app,0,0,"View Headers","_Okay","\33cPlease select a message.",0);
			break;
		}
		case MEN_MOVE:
			move_multi(0);
			break;
		case MEN_COPY:
			move_multi(1);
			break;
		case MEN_KILLMESS:
		{
			getGdataDisplayed(&gdata);
			int result = 0;
			getMdataActivePos(&result);
			if(result!=MUIV_NList_Active_Off) {
				//if(!downloading_headers) {
					getMdataActive(&mdata);
					killmess(gdata,mdata);
				/*}
				else
					MUI_RequestA(app,0,0,"Kill Message","_Okay","\33cPlease wait for downloading to finish first.",0);*/
			}
			else
				MUI_RequestA(app,0,0,"Kill","_Okay","\33cPlease select a message!",0);
			break;
		}
		case MEN_YAMADDRESS:
		{
			getGdataDisplayed(&gdata);
			int result = 0;
			getMdataActivePos(&result);
			if(result!=MUIV_NList_Active_Off) {
				getMdataActive(&mdata);
				exportAddress(gdata,mdata);
			}
			else
				MUI_RequestA(app,0,0,"Export Address","_Okay","\33cPlease select a message!",0);
			break;
		}
		case MEN_DOWNLOADBODY:
			/*if(delete_dis)
				MUI_RequestA(app,0,0,"Downloading Message","_Okay","\33cNewsCoaster cannot download articles whilst\nother messages are already being downloaded, sorry.",0);
			else*/
			{
				//get(NLIST_messagelistdata,MUIA_NList_Entries,&entries);
				entries = getMdataVisibleEntries();
				getGdataDisplayed(&gdata);
				sleepAll(TRUE);
				int max = 0;
				for(int k=0;k<entries;k++) {
					if(isMdataSelected(k)) {
						getMdataVisible(k,&mdata);
						if(mdata->flags[12])
							max++;
					}
				}
				if(max > 0) {
					StatusWindow * statusWindow = new StatusWindow(app,"Downloading bodies..");;
					MessageListData **mdataptr = new MessageListData *[max];
					int index = 0;
					int ndel = 0;
					for(k=0;k<entries;k++) {
						if(isMdataSelected(k)) {
							getMdataVisible(k,&mdata);
							if(mdata->flags[12]==TRUE) {
								index++; // increment first
								BOOL available = TRUE;
								BOOL okay = getBody(&available,gdata,mdata,statusWindow,index,max,(index==1),FALSE);
								if(!available && (account.flags & Account::NODELONLINE)==0 ) {
									mdataptr[ndel++] = mdata;
								}
								if(!okay && available)
									break;
								redrawMdata(k);
							}
						}
					}
					redrawGdataAll();
					if(ndel > 0 )
						statusWindow->setText("Deleting no longer available headers..\n");
					if(ndel > 0) {
						//clearThreadView();
						for(k=0;k<ndel;k++) {
							// delete message
							delete_mess(gdata,mdataptr[k],FALSE);
						}
						threadView();
					}
					delete [] mdataptr;
					delete statusWindow;
				}
				sleepAll(FALSE);
			}
			break;
		case MEN_SELECTALL:
			if(account.mdata_view==0)
				DoMethod(NLIST_messagelistdata,MUIM_NList_Select,MUIV_NList_Select_All,MUIV_NList_Select_On,NULL);
			else
				DoMethod(LISTTREE_messagelistdata,MUIM_NList_Select,MUIV_NList_Select_All,MUIV_NList_Select_On,NULL);
			break;
		case MEN_SELECTNONE:
			if(account.mdata_view==0)
				DoMethod(NLIST_messagelistdata,MUIM_NList_Select,MUIV_NList_Select_All,MUIV_NList_Select_Off,NULL);
			else
				DoMethod(LISTTREE_messagelistdata,MUIM_NList_Select,MUIV_NList_Select_All,MUIV_NList_Select_Off,NULL);
			break;
		case MEN_SELECTTOGGLE:
			if(account.mdata_view==0)
				DoMethod(NLIST_messagelistdata,MUIM_NList_Select,MUIV_NList_Select_All,MUIV_NList_Select_Toggle,NULL);
			else
				DoMethod(LISTTREE_messagelistdata,MUIM_NList_Select,MUIV_NList_Select_All,MUIV_NList_Select_Toggle,NULL);
			break;
		case MEN_SELECTFROM:
		{
			//get(NLIST_messagelistdata,MUIA_NList_Entries,&entries);
			entries = getMdataVisibleEntries();
			int result = 0;
			getMdataActivePos(&result);
			if(result!=MUIV_NList_Active_Off) {
				MessageListData * mdata2=NULL;
				getMdataActive(&mdata);
				for(int k=0;k<entries;k++) {
					getMdataVisible(k,&mdata2);
					//DoMethod(NLIST_messagelistdata,MUIM_NList_GetEntry,k,&mdata2);
					if(stricmp(mdata->from,mdata2->from)==0) {
						if(account.mdata_view==0)
							DoMethod(NLIST_messagelistdata,MUIM_NList_Select,k,MUIV_NList_Select_On,NULL);
						else
							DoMethod(LISTTREE_messagelistdata,MUIM_NList_Select,k,MUIV_NList_Select_On,NULL);
					}
					else {
						if(account.mdata_view==0)
							DoMethod(NLIST_messagelistdata,MUIM_NList_Select,k,MUIV_NList_Select_Off,NULL);
						else
							DoMethod(LISTTREE_messagelistdata,MUIM_NList_Select,k,MUIV_NList_Select_Off,NULL);
					}
				}
			}
			break;
		}
		case MEN_SELECTSUBJECT:
		{
			//get(NLIST_messagelistdata,MUIA_NList_Entries,&entries);
			entries = getMdataVisibleEntries();
			int result = 0;
			getMdataActivePos(&result);
			if(result!=MUIV_NList_Active_Off) {
				MessageListData * mdata2=NULL;
				getMdataActive(&mdata);
				temp = mdata->subject;
				while(*temp!=0 && (strincmp_q(temp,"RE: ",4)==0 || strincmp_q(temp,"SV: ",4)==0))
					temp += 4;
				for(int k=0;k<entries;k++) {
					getMdataVisible(k,&mdata2);
					//DoMethod(NLIST_messagelistdata,MUIM_NList_GetEntry,k,&mdata2);
					temp2 = mdata2->subject;
					while(*temp2!=0 && (strincmp_q(temp2,"RE: ",4)==0 || strincmp_q(temp2,"SV: ",4)==0))
						temp2 += 4;
					if(stricmp(temp,temp2)==0) {
						if(account.mdata_view==0)
							DoMethod(NLIST_messagelistdata,MUIM_NList_Select,k,MUIV_NList_Select_On,NULL);
						else
							DoMethod(LISTTREE_messagelistdata,MUIM_NList_Select,k,MUIV_NList_Select_On,NULL);
					}
					else {
						if(account.mdata_view==0)
							DoMethod(NLIST_messagelistdata,MUIM_NList_Select,k,MUIV_NList_Select_Off,NULL);
						else
							DoMethod(LISTTREE_messagelistdata,MUIM_NList_Select,k,MUIV_NList_Select_Off,NULL);
					}
				}
			}
			break;
		}
		case MEN_SELECTREAD:
		case MEN_SELECTUNREAD: {
			entries = getMdataVisibleEntries();
			//get(NLIST_messagelistdata,MUIA_NList_Entries,&entries);
			MessageListData * mdata=NULL;
			for(int k=0;k<entries;k++) {
				getMdataVisible(k,&mdata);
				//DoMethod(NLIST_messagelistdata,MUIM_NList_GetEntry,k,&mdata);
				if(mdata->flags[1] == (returnID==MEN_SELECTUNREAD)) {
					if(account.mdata_view==0)
						DoMethod(NLIST_messagelistdata,MUIM_NList_Select,k,MUIV_NList_Select_On,NULL);
					else
						DoMethod(LISTTREE_messagelistdata,MUIM_NList_Select,k,MUIV_NList_Select_On,NULL);
				}
				else {
					if(account.mdata_view==0)
						DoMethod(NLIST_messagelistdata,MUIM_NList_Select,k,MUIV_NList_Select_Off,NULL);
					else
						DoMethod(LISTTREE_messagelistdata,MUIM_NList_Select,k,MUIV_NList_Select_Off,NULL);
				}
			}
			break;
		}
		case MEN_MARKUNREAD:
		case MEN_MARKREAD:
			//get(NLIST_messagelistdata,MUIA_NList_Entries,&entries);
			entries = getMdataVisibleEntries();
			if(entries>0) {
				getGdataDisplayed(&gdata);
				if(gdata->ID>=0) {
					setMdataQuiet(TRUE);
					set(app,MUIA_Application_Sleep,TRUE);
					MessageListData **mdataptr = new MessageListData *[entries];
					int count = 0;
					for(int k=0;k<entries;k++) {
						if(isMdataSelected(k)) {
							getMdataVisible(k,&mdata);
							if(returnID == MEN_MARKUNREAD) {
								if(!mdata->flags[1]) {
									mdata->flags[1]=TRUE;
									mdataptr[count++] = mdata;
								}
							}
							else {
								if(mdata->flags[1]) {
									mdata->flags[1]=FALSE;
									mdataptr[count++] = mdata;
								}
							}
							redrawMdata(k);
						}
					}
					//gdata->flags[1]=TRUE;
					write_index_update_multi(gdata,mdataptr,count,NLIST_messagelistdata);
					delete [] mdataptr;
					if(returnID==MEN_MARKUNREAD)
						gdata->num_unread += count;
					else
						gdata->num_unread -= count;
					setMdataQuiet(FALSE);
					update_screen_title(gdata);
					set(app,MUIA_Application_Sleep,FALSE);
				}
				else {
					if(returnID==MEN_MARKUNREAD)
						MUI_RequestA(app,0,0,"Mark Message","_Okay","\33cOnly messages in newsgroups can be marked as unread!",0);
					else
						MUI_RequestA(app,0,0,"Mark Message","_Okay","\33cOnly messages in newsgroups can be marked as read!",0);
				}
			}
			break;
		case MEN_MARKHELD:
		case MEN_MARKQUEUED:
		case MEN_MARKIMPORTANT:
		case MEN_MARKNORMAL:
			//get(NLIST_messagelistdata,MUIA_NList_Entries,&entries);
			entries = getMdataVisibleEntries();
			if(entries>0) {
				getGdataDisplayed(&gdata);
				if(gdata->ID==-1 || (returnID!=MEN_MARKHELD && returnID!=MEN_MARKQUEUED)) {
					setMdataQuiet(TRUE);
					set(app,MUIA_Application_Sleep,TRUE);
					MessageListData **mdataptr = new MessageListData *[entries];
					int count = 0;
					for(int k=0;k<entries;k++) {
						if(isMdataSelected(k)) {
							getMdataVisible(k,&mdata);
							if(returnID == MEN_MARKHELD) {
								if(!mdata->flags[0]) {
									mdata->flags[0] = TRUE;
									mdataptr[count++] = mdata;
								}
							}
							else if(returnID == MEN_MARKQUEUED) {
								if(mdata->flags[0]) {
									mdata->flags[0] = FALSE;
									mdataptr[count++] = mdata;
								}
							}
							else if(returnID == MEN_MARKNORMAL) {
								if(mdata->flags[13]) {
									mdata->flags[13] = FALSE;
									mdataptr[count++] = mdata;
								}
							}
							else if(returnID == MEN_MARKIMPORTANT) {
								if(!mdata->flags[13]) {
									mdata->flags[13] = TRUE;
									mdataptr[count++] = mdata;
								}
							}
							redrawMdata(k);
						}
					}
					//gdata->flags[1]=TRUE;
					write_index_update_multi(gdata,mdataptr,count,NLIST_messagelistdata);
					delete [] mdataptr;
					setMdataQuiet(FALSE);
					set(app,MUIA_Application_Sleep,FALSE);
				}
				else {
					if(returnID == MEN_MARKHELD)
						MUI_RequestA(app,0,0,"Mark Message","_Okay","\33cOnly messages in outgoing can be marked as held!",0);
					else
						MUI_RequestA(app,0,0,"Mark Message","_Okay","\33cOnly messages in outgoing can be marked as queued!",0);
				}
			}
			break;
		case MEN_CURRENTDATE:
			//get(NLIST_messagelistdata,MUIA_NList_Entries,&entries);
			entries = getMdataVisibleEntries();
			if(entries>0) {
				getGdataDisplayed(&gdata);
				if(gdata->ID==-1) {
					setMdataQuiet(TRUE);
					set(app,MUIA_Application_Sleep,TRUE);
					//char date[256] = "";
					for(int k=0;k<entries;k++) {
						if(isMdataSelected(k)) {
							getMdataVisible(k,&mdata);
							//DateHandler::get_datenow(mdata->date,getGMTOffset(),account.bst);
							//DateHandler::read_date(&mdata->ds,mdata->date,mdata->c_date,mdata->c_time);
							DateHandler::get_datenow(status_buffer_g,getGMTOffset(),account.bst);
							//printf("DATE: %s\n",status_buffer_g);
							DateHandler::read_date(&mdata->ds,status_buffer_g,mdata->c_date,mdata->c_time);
							//printf("%s %s\n",mdata->c_date,mdata->c_time);
							mdata->datec[0] = '\0';
							changedate(gdata,mdata,status_buffer_g,NLIST_messagelistdata);
							redrawMdata(k);
						}
					}
					setMdataQuiet(FALSE);
					//gdata->flags[1]=TRUE;
					set(app,MUIA_Application_Sleep,FALSE);
				}
				else
					MUI_RequestA(app,0,0,"Change Date","_Okay","\33cYou can only change the date of\nyour messages that have not been sent.",0);
			}
			break;
		case MEN_JOINMSGS:
			get(wnd_joinmsgs,MUIA_Window_Open,&yesno);
			if(!yesno) {
				set(STR_joinmsgs_SUBJECT,MUIA_String_Contents,"");
				DoMethod(NLIST_joinmsgs_MSGS,MUIM_NList_Clear);
				//get(NLIST_messagelistdata,MUIA_NList_Entries,&entries);
				entries = getMdataVisibleEntries();
				if(entries>0) {
					getGdataDisplayed(&gdata);
					setMdataQuiet(TRUE);
					set(app,MUIA_Application_Sleep,TRUE);

					int count = 0;
					for(int k=0;k<entries;k++) {
						if(isMdataSelected(k)) {
							getMdataVisible(k,&mdata);

							if(mdata->flags[12]==TRUE) {
								// we need to download the BODY!
								sleepAll(TRUE);
								BOOL available = TRUE;
								getBody(&available,gdata,mdata);
								sleepAll(FALSE);
							}

							if(mdata->flags[12]==FALSE) {
								if(count==0) {
									NewMessage newmess;
									get_refs(&newmess,gdata,mdata,GETREFS_NONE);
									set(STR_joinmsgs_SUBJECT,MUIA_String_Contents,newmess.subject);
								}

								MessageListData * mdata2 = new MessageListData();
								*mdata2 = *mdata;
								mdata2->flags[6] = gdata->ID;
								DoMethod(NLIST_joinmsgs_MSGS,MUIM_NList_InsertSingle,mdata2,MUIV_NList_Insert_Bottom);
								count++;
							}
						}
					}

					setMdataQuiet(FALSE);
					set(app,MUIA_Application_Sleep,FALSE);
					set(wnd_joinmsgs,MUIA_Window_Open,TRUE);
				}
				set(wnd_joinmsgs,MUIA_Window_Open,TRUE);
			}
			else {
				set(wnd_joinmsgs,MUIA_Window_Open,TRUE);
			}
			break;
		case MEN_ACCOUNT:
			/*get(wnd_write,MUIA_Window_Open,&yesno);
			if(!yesno)
			{*/
				get(wnd_account,MUIA_Window_Open,&yesno);
				if(yesno)
					set(wnd_account,MUIA_Window_Open,TRUE);
				else
				{
				set(STR_acc_NAME,MUIA_String_Contents,account.name);
				set(STR_acc_EMAIL,MUIA_String_Contents,account.email);
				set(STR_acc_REALEMAIL,MUIA_String_Contents,account.realemail);
				set(STR_acc_ORG,MUIA_String_Contents,account.org);
				set(STR_acc_SMTP,MUIA_String_Contents,account.smtp);
				set(STR_acc_DOMAIN,MUIA_String_Contents,account.domain);
				set(STR_acc_FOLLOWUPTEXT,MUIA_String_Contents,account.followup_text);
				set(STR_acc_CHARSETWRITE,MUIA_String_Contents,account.charset_write);
				set(CY_acc_TIMEZONE,MUIA_Cycle_Active,account.timezone+12);
				set(CM_acc_USELOCALETZ,MUIA_Selected,account.uselocaletz);
				set(CM_acc_BST,MUIA_Selected,account.bst);
				set(CY_acc_DATEFORMAT,MUIA_Cycle_Active,account.dateformat);
				if((account.flags & Account::LOGGING)!=0)
					set(CM_acc_LOGGING,MUIA_Selected,TRUE);
				else
					set(CM_acc_LOGGING,MUIA_Selected,FALSE);
				if((account.flags & Account::LOGDEL)!=0)
					set(CM_acc_LOGDEL,MUIA_Selected,TRUE);
				else
					set(CM_acc_LOGDEL,MUIA_Selected,FALSE);
				set(CM_acc_VGROUPDL,MUIA_Selected,account.vgroupdl);
				set(CM_acc_NOCONFIRMDEL,MUIA_Selected,account.noconfirmdel);
				if((account.flags & Account::NODELONLINE)==0) {
					// opposite logic, so that it is turned on by default when
					// upgrading from older version before this flag
					set(CM_acc_DELONLINE,MUIA_Selected,TRUE);
				}
				else
					set(CM_acc_DELONLINE,MUIA_Selected,FALSE);

				if((account.flags & Account::NOCONFIRMQUIT)==0) {
					// opposite logic, so that it is turned on by default when
					// upgrading from older version before this flag
					set(CM_acc_CONFIRMQUIT,MUIA_Selected,TRUE);
				}
				else
					set(CM_acc_CONFIRMQUIT,MUIA_Selected,FALSE);

				set(CM_acc_QUIETDL,MUIA_Selected,((account.flags & Account::QUIETDL)!=0));

				set(CM_acc_CHECKFORDUPS,MUIA_Selected,((account.flags & Account::CHECKFORDUPS)!=0));

				set(CM_acc_XNEWS,MUIA_Selected,account.xnews);
				//set(CM_acc_USESIG,MUIA_Selected,account.usesig);
				set(STR_acc_LINELENGTH,MUIA_String_Integer,account.linelength);
				if(account.rewrap==1)
					set(CM_acc_REWRAP,MUIA_Selected,TRUE);
				else
					set(CM_acc_REWRAP,MUIA_Selected,FALSE);
				if((account.flags & Account::SNIPSIG)!=0)
					set(CM_acc_SNIPSIG,MUIA_Selected,TRUE);
				else
					set(CM_acc_SNIPSIG,MUIA_Selected,FALSE);
				set(CY_acc_XNO,MUIA_Cycle_Active,account.xno);
				set(CY_acc_SIG,MUIA_Cycle_Active,0);
				cy_current_sig=0;
				
				set(CM_acc_LISTFLAGS,MUIA_Selected,((account.listflags & Account::LISTFLAGS)!=0));
				set(CM_acc_LISTFROMGROUP,MUIA_Selected,((account.listflags & Account::LISTFROMGROUP)!=0));
				set(CM_acc_LISTDATE,MUIA_Selected,((account.listflags & Account::LISTDATE)!=0));
				set(CM_acc_LISTSUBJECT,MUIA_Selected,((account.listflags & Account::LISTSUBJECT)!=0));
				set(CM_acc_LISTSIZE,MUIA_Selected,((account.listflags & Account::LISTSIZE)!=0));
				set(CM_acc_LISTLINES,MUIA_Selected,((account.listflags & Account::LISTLINES)!=0));
				
				DoMethod(NLIST_acc_MIMEPREFS,MUIM_NList_Clear);
				for(int k=0;k<account.mimeprefsno;k++) {
					ptr=(MIMEPrefs *)new MIMEPrefs;
					*(MIMEPrefs *)ptr=*account.mimeprefs[k];
					DoMethod(NLIST_acc_MIMEPREFS,MUIM_NList_InsertSingle,ptr,MUIV_NList_Insert_Bottom);
				}
				if(account.mimeprefsno>0)
					set(NLIST_acc_MIMEPREFS,MUIA_NList_Active,MUIV_NList_Active_Top);
				set(STR_acc_MIMEDEF,MUIA_String_Contents,account.defviewer);
				set(STR_acc_MIME,MUIA_String_Contents,"");
				set(STR_acc_MIMEVIEW,MUIA_String_Contents,"");
				set(CY_acc_READHEADER,MUIA_Cycle_Active,account.readheader_type);
				set(STR_acc_READHEADER,MUIA_String_Contents,account.readheaders);
				MUI_PenSpec *pen_quote2 = new MUI_PenSpec;
				MUI_PenSpec *pen_col = new MUI_PenSpec;
				*pen_quote2 = account.pen_acc_text_quote2;
				*pen_col = account.pen_acc_text_col;
				set(PEN_acc_TEXT_QUOTE2,MUIA_Pendisplay_Spec,pen_quote2);
				set(PEN_acc_TEXT_COL,MUIA_Pendisplay_Spec,pen_col);
				set(CM_acc_MULTIPLEVWS,MUIA_Selected,account.multiplevws);
				set(wnd_account,MUIA_Window_ActiveObject,STR_acc_NAME);
				DoMethod(ED_acc_SIG,MUIM_TextEditor_ClearText);
				set(NLIST_acc_SERVERS,MUIA_NList_Active,MUIV_NList_Active_Top);
				set(pages_account,MUIA_Group_ActivePage,0);
				set(wnd_account,MUIA_Window_Open,TRUE);
				}
			/*}
			else
			{
				MUI_RequestA(app,0,0,"Accounts","_Okay","\33cIt is not possible to change\nthe Program settings whilst editing a message.\nPlease finish editing current message",0);
				set(wnd_write,MUIA_Window_Open,TRUE);
			}*/
			break;
		case MEN_KILLFILE:
			set(CM_acc_SIZEKILL,MUIA_Selected,account.use_sizekill);
			set(wnd_killfile,MUIA_Window_Open,TRUE);
			break;
		case MEN_USERS:
			set(wnd_users,MUIA_Window_Open,TRUE);
			break;
		case USERS_NEW:
			get(wnd_newuser,MUIA_Window_Open,&yesno);
			if(!yesno) {
				set(STR_newuser_USER,MUIA_String_Contents,"");
				set(STR_newuser_PASS,MUIA_String_Contents,"");
				set(CM_newuser_PASS,MUIA_Selected,FALSE);
				set(STR_newuser_DATALOC,MUIA_String_Contents,"PROGDIR:");
				set(CM_newuser_SUP,MUIA_Selected,TRUE);
				set(CM_newuser_SUP,MUIA_Selected,FALSE);
			}
			set(wnd_newuser,MUIA_Window_Open,TRUE);
			set(wnd_newuser,MUIA_Window_ActiveObject,STR_newuser_USER);
			break;
		case USERS_DELETE:
		{
			int val = 0;
			get(NLIST_users_LIST,MUIA_NList_Active,&val);
			if(val!=MUIV_NList_Active_Off) {
				User *user = NULL;
				DoMethod(NLIST_users_LIST,MUIM_NList_GetEntry,val,&user);
				if(stricmp(currentUser->getName(),user->getName())==0)
					MUI_RequestA(app,0,0,"Delete User","_Okay","\33cYou may not delete the current login!\nIf you wish to delete yourself, please login under a new user, and\nthen delete this user.",0);
				else
				{
				int result = MUI_RequestA(app,0,0,"Delete User","Delete|_Cancel","\33cAre you *sure* you wish\nto delete this User?\n",0);
				if(result==1)
				{
					//result=MUI_RequestA(app,0,0,"Delete User","Prefs and News Items|Prefs Only|Neither","The database entry for this user has been deleted.\nYou may now either:\n- Delete all their prefs and news items\n- Delete their prefs only\n- Or do neither.",0);
					result = MUI_RequestA(app,0,0,"Delete User","Yes|No","The database entry for this user has been deleted.\nDo you now wish to delete all their prefs?",0);
					correctDrawer(status_buffer_g,user->dataLocation);
					if(result!=0)
					{
						// delete prefs
						/*sprintf(command,"list \"%s\"",status_buffer_g);
						Execute(command,NULL,NULL);*/
						sprintf(command,"delete \"%s.prefs\" >NIL:",status_buffer_g);
						Execute(command,NULL,NULL);
						sprintf(command,"delete \"%s.killfile\" >NIL:",status_buffer_g);
						Execute(command,NULL,NULL);
					}
					/*if(result==1)
					{
						// delete all news items
						result=MUI_RequestA(app,0,0,"Delete All News Items","Delete|_Cancel","\33cAre you *sure* you wish\nto delete all news items for this user?\n",0);
						if(result==1)
						{
							printf("deleting all news..");
						}
					}*/
					DoMethod(NLIST_users_LIST,MUIM_NList_Remove,val);
					saveUsers();
				}
				}
			}
			break;
		}
		case NEWUSER_OKAY:
		{
			strcpy(status_buffer_g,getstr(STR_newuser_USER));
			if(strlen(status_buffer_g)<3)
			{
				MUI_RequestA(app,0,0,"New User","_Okay","\33cUser name must be at least 3 characters.\nPlease enter a longer user name.",0);
				break;
			}
			correctDrawer(filename,getstr(STR_newuser_DATALOC));
			int val = checkUniqueUser(getstr(STR_newuser_USER),filename);
			if(val==1) {
				MUI_RequestA(app,0,0,"New User","_Okay","\33cThis user name already exists.\nPlease enter another one.",0);
				break;
			}
			else if(val==2) {
				MUI_RequestA(app,0,0,"New User","_Okay","\33cThis news directory is being used by another user.\nPlease select somewhere else.",0);
				break;
			}
			get(CM_newuser_PASS,MUIA_Selected,&val);
			strcpy(status_buffer_g,getstr(STR_newuser_PASS));
			if(val==TRUE && strlen(status_buffer_g)<4) {
				MUI_RequestA(app,0,0,"New User","_Okay","\33cPassword must be at least 4 characters.\nPlease enter a longer password, or untick the password.",0);
				break;
			}
			if(createDrawer(filename)==FALSE)
			{
				sprintf(status_buffer_g,"\33cError! Couldn't create folder:\n%s",getstr(STR_newuser_DATALOC));
				MUI_RequestA(app,0,0,"New User","_Okay",status_buffer_g,0);
				break;
			}
			set(wnd_newuser,MUIA_Window_Open,FALSE);
			User *user = NULL;
			if(val==TRUE)
				user = new User(getstr(STR_newuser_USER),getstr(STR_newuser_PASS));
			else
				user = new User(getstr(STR_newuser_USER),NULL);
			//strcpy(user->dataLocation,getstr(STR_newuser_DATALOC));
			//correctDrawer(user->dataLocation,getstr(STR_newuser_DATALOC));
			strcpy(user->dataLocation,filename);
			get(CM_newuser_SUP,MUIA_Selected,&val);
			user->setSupervisor(val);
			addUser(user);
			// copy prefs?
			get(CM_newuser_COPYPREFS,MUIA_Selected,&val);
			if(val) {
				sprintf(filename,"%s.prefs",user->dataLocation);
				account.save_tofile(filename);
				sprintf(filename,"%s.servers",user->dataLocation);
				save_servers(filename);
			}
			// decides whether in login stage or not by seeing if wnd_main is closed or open..
			get(wnd_main,MUIA_Window_Open,&val);
			if(val)
				DoMethod(NLIST_users_LIST,MUIM_NList_InsertSingle,user,MUIV_NList_Insert_Bottom);
			else
				currentUser=user; // must be during login process
			newuseradded=1;
			break;
		}
		case MEN_CPWD:
			get(wnd_cpwd,MUIA_Window_Open,&yesno);
			if(!yesno)
			{
				set(STR_cpwd_PASS,MUIA_String_Contents,"");
				set(CM_cpwd_PASS,MUIA_Selected,currentUser->requiresPassword());
				/*strcpy(status_buffer_g,"Please enter a new password,\nor press cancel to leave it unchanged.");
				set(TXT_cpwd_INFO,MUIA_String_Contents,status_buffer_g);*/
			}
			set(wnd_cpwd,MUIA_Window_Open,TRUE);
			break;
		case CPWD_OKAY:
		{	
			set(wnd_cpwd,MUIA_Window_Open,FALSE);
			int val = 0;
			get(CM_cpwd_PASS,MUIA_Selected,&val);
			strcpy(status_buffer_g,getstr(STR_cpwd_PASS));
			if(val==TRUE && strlen(status_buffer_g) < 4) {
				MUI_RequestA(app,0,0,"Change Password","_Okay","\33cPassword must be at least 4 characters.\nPlease enter a longer password, or untick the password.",0);
				break;
			}
			if(val==TRUE)
				currentUser->setPassword(status_buffer_g);
			else
				currentUser->setPassword(NULL);
			replaceUser(currentUser);
			loadUsers();
			break;
		}
		case MEN_MUIPREFS:
			DoMethod(app,MUIM_Application_OpenConfigWindow,0);
			break;
		case NG_CHANGED:
			if(old_gdata) {
				//printf("old_gdata->ID = %d\n",old_gdata->ID);
				//printf("old_gdata->flags[1] = %d\n",old_gdata->flags[1]);
				if(old_gdata->flags[1])
					write_index(1);
			}
			getGdataActive(&gdata);
			if(gdata!=NULL) {
				v_gdata=gdata;
				/*
				//printf("%d %d\n",old_gdata,gdata);
				if(old_gdata != NULL) {
					Server *old_server = getServer(old_gdata->serverID);
					Server *server = getServer(gdata->serverID);
					//printf("%d %d\n",old_server->ID,server->ID);
					if(old_server->ID != server->ID) {
						closeSockets(); // disconnect when in online mode - just in case the newsgroup is on a different newsserver
					}
				}
				*/
				if(gdata->ID != gdata_readID) {
					read_index();
					//find oldest unread message (if there is)
					jumpto_unread();
				}
				gdata_readID=gdata->ID;
				getGdataActive(&old_gdata);
				//printf("  old_gdata->ID is now %d\n",old_gdata->ID);
				setEnabled();
			}
			break;
		case NEW_SORT:
		{
			int val = 0;
			if(account.mdata_view==0)
				get(NLIST_messagelistdata,MUIA_NList_TitleClick,&val);
			else
				get(LISTTREE_messagelistdata,MUIA_NList_TitleClick,&val);

			/*if(val>0) {
				val--; // so correct
				getGdataDisplayed(&gdata);
				if(gdata->ID<0 && val==2)
					val=-1; // newsgroup column replaces From in outgoing/sent/deleted
				if(val==account.sorttype)
					account.sorttypedir=-account.sorttypedir;
				else {
					account.sorttype=val;
					account.sorttypedir=1;
				}
				set(wnd_main,MUIA_Window_Sleep,TRUE);
				DoMethod(NLIST_messagelistdata,MUIM_NList_Sort);
				set(wnd_main,MUIA_Window_Sleep,FALSE);
			}*/
			int icol = getInternalColumn(val);
			int sorttype = 0;
			getGdataDisplayed(&gdata);
			if(getSortType(&sorttype,icol,gdata->ID)) {
				if(account.sorttype == sorttype)
					account.sorttypedir = -account.sorttypedir;
				else {
					account.sorttype = sorttype;
					account.sorttypedir = 1;
				}
				//printf("%d %d %d\n",val,icol,account.sorttype);
				set(wnd_main,MUIA_Window_Sleep,TRUE);
				DoMethod(NLIST_messagelistdata,MUIM_NList_Sort);
				set(wnd_main,MUIA_Window_Sleep,FALSE);
				threadView();
			}
			break;
		}
		case NNG_OKAY:
			/*if(delete_dis)
			{
				MUI_RequestA(app,0,0,"Not Available","_Okay","\33cThis function not available whilst\nNewsCoaster is connected with the newsserver!",0);
				break;
			}
			else*/
			{
			while(TRUE) {
				sprintf(filename,"NewsCoasterData:Folder_%d",nextID);
				if(exists(filename))
					nextID++;
				else
					break;
			}
			lock=CreateDir(filename);
			if(lock) {
				UnLock(lock);
				lock=NULL;
				gdata=new GroupData();
				gdata->ID=nextID;
				gdata->flags[0]=FALSE;
				strcpy(gdata->name,getstr(STR_nng_NAME));
				strcpy(gdata->desc,getstr(STR_nng_DESC));

				char comment[81] = "";
				strncpy(comment,*gdata->desc=='\0' ? gdata->name : gdata->desc,80);
				comment[80] = '\0';
				SetComment(filename,comment);

				gdata->nummess=0;
				gdata->num_unread=0;
				gdata->nextmID=0;
				get(CM_nng_S,MUIA_Selected,&gdata->s);
				get(CY_nng_DEFSIG,MUIA_Cycle_Active,&gdata->defsig);
				gdata->defsig--;
				DateStamp(&gdata->lastdlds); // download from now on
				int val = 0;
				get(CY_nng_MAXDL,MUIA_Cycle_Active,&val);
				if(val==0)
					gdata->max_dl=-1;
				else
					get(STR_nng_MAXDL,MUIA_String_Integer,&gdata->max_dl);
				get(CY_nng_MAXL,MUIA_Cycle_Active,&val);
				if(val==0)
					gdata->flags[2]=0;
				else {
					get(STR_nng_MAXL,MUIA_String_Integer,&gdata->flags[2]);
					if(gdata->flags[2]==0)
						gdata->flags[2]=1;
				}
				get(CY_nng_MAXAGE,MUIA_Cycle_Active,&gdata->flags[6]);
				get(STR_nng_MAXAGE,MUIA_String_Integer,&gdata->flags[7]);
				get(CY_nng_OFFLINE,MUIA_Cycle_Active,&gdata->flags[5]);
				gdata->serverID = 0;
				if(nng_defserver != 0) {
					// messing about so that we use default if the Server has since been deleted
					Server *server = getServer(nng_defserver); // will choose default if been deleted
					if(server->ID != nng_defserver) // force default
						gdata->serverID = 0;
					else if(server->def)
						gdata->serverID = 0;
					else
						gdata->serverID = server->ID;
				}
				insertGdata(gdata,FALSE);
				redrawGdataAll();
				//sprintf(command,"copy NewsCoaster:default.index NewsCoasterData:Folder_%d/.index",nextID);
				//Execute(command,NULL,NULL);
				writeEmptyIndex(gdata->ID);
				
				nextID++;
				account.save_data();
			}
			else
				MUI_RequestA(app,0,0,"Error","_Okay","\33cCannot create Folder!",0);
			// no break
			}
		case NNG_CANCEL:
			set(wnd_newnewsgroup,MUIA_Window_Open,FALSE);
			set(STR_nng_NAME,MUIA_String_Contents,"");
			set(STR_nng_DESC,MUIA_String_Contents,"");
			nng_defserver = 0;
			break;
		case ENG_OKAY:
			/*if(delete_dis)
			{
				MUI_RequestA(app,0,0,"Not Available","_Okay","\33cThis function not available whilst\nNewsCoaster is connected with the newsserver!",0);
				break;
			}
			else*/
			{
			strcpy(ng_edit->name,getstr(STR_eng_NAME));
			strcpy(ng_edit->desc,getstr(STR_eng_DESC));

			getFolderPath(filename,ng_edit->ID);
			char comment[81] = "";
			strncpy(comment,*ng_edit->desc=='\0' ? ng_edit->name : ng_edit->desc,80);
			comment[80] = '\0';
			SetComment(filename,comment);

			get(CY_eng_DEFSIG,MUIA_Cycle_Active,&ng_edit->defsig);
			ng_edit->defsig--;
			get(CM_eng_S,MUIA_Selected,&ng_edit->s);
			int val = 0;
			get(CY_eng_MAXDL,MUIA_Cycle_Active,&val);
			if(val==0)
				ng_edit->max_dl=-1;
			else
				get(STR_eng_MAXDL,MUIA_String_Integer,&ng_edit->max_dl);
			get(CY_eng_MAXL,MUIA_Cycle_Active,&val);
			if(val==0)
				ng_edit->flags[2]=0;
			else {
				get(STR_eng_MAXL,MUIA_String_Integer,&ng_edit->flags[2]);
				if(ng_edit->flags[2]==0)
					ng_edit->flags[2]=1;
			}
			get(CY_eng_MAXAGE,MUIA_Cycle_Active,&ng_edit->flags[6]);
			get(STR_eng_MAXAGE,MUIA_String_Integer,&ng_edit->flags[7]);
			get(CY_eng_OFFLINE,MUIA_Cycle_Active,&ng_edit->flags[5]);
			redrawGdataAll();
			ng_edit=NULL;
			account.save_data();
			// no break
			}
		case ENG_CANCEL:
			set(wnd_editng,MUIA_Window_Open,FALSE);
			set(STR_eng_NAME,MUIA_String_Contents,"");
			set(STR_nng_DESC,MUIA_String_Contents,"");
			break;
		case NGADV_OKAY:
		{
			get(CM_ngadv_APPVHD,MUIA_Selected,&ng_editadv->moreflags[0]);
			strcpy(ng_editadv->appv_hd,getstr(STR_ngadv_APPVHD));
			get(CM_ngadv_ALTNAME,MUIA_Selected,&ng_editadv->moreflags[1]);
			strcpy(ng_editadv->alt_name,getstr(STR_ngadv_ALTNAME));
			get(CM_ngadv_ALTEMAIL,MUIA_Selected,&ng_editadv->moreflags[2]);
			strcpy(ng_editadv->alt_email,getstr(STR_ngadv_ALTEMAIL));
			Server *oldsv = getServer(ng_editadv->serverID);

			int val = 0;
			get(CM_ngadv_SERVER,MUIA_Selected,&val);
			if(val)
				ng_editadv->serverID = 0;
			else {
				get(CY_ngadv_SERVER,MUIA_Cycle_Active,&val);
				Server *server = getServer(server_list[val]); // will choose default if been deleted
				if(server->ID != server_list[val]) // force default
					ng_editadv->serverID = 0;
				else
					ng_editadv->serverID = server->ID;
			}

			get(CM_ngadv_SERVERPOST,MUIA_Selected,&ng_editadv->moreflags[4]);

			Server *newsv = getServer(ng_editadv->serverID);
			if(oldsv->ID != newsv->ID) { // reset article pointer?
				int result = MUI_RequestA(app,0,0,"Reset Article Pointer","_Reset|_Don't Reset","\33cYou have changed the NNTP server for this group, do you wish to reset the article pointer?\n(see documentation for details - if unsure, you should Reset).",0);
				if(result == 1)
					resetArticlePointers(ng_editadv);

				GroupData *active_gdata = NULL;
				getGdataActive(&active_gdata);
				if(ng_editadv == active_gdata)
					setGdataHelpText(active_gdata); // update help bubble text, since using a different newsserver
			}
			redrawGdataAll();
			ng_editadv=NULL;
			account.save_data();
			// no break
		}
		case NGADV_CANCEL:
			set(wnd_ngadv,MUIA_Window_Open,FALSE);
			break;
		case JOINMSGS_JOIN:
		{
			nLog("JOINMSGS_JOIN:\n");
			get(NLIST_joinmsgs_MSGS,MUIA_NList_Entries,&entries);
			if(entries > 0) {
				DoMethod(NLIST_joinmsgs_MSGS,MUIM_NList_GetEntry,0,&mdata);
				/*int gID = mdata->flags[6];
				int g_pos = get_gdataPos(gID);
				gdata = NULL;
				if(g_pos != -1)
					getGdata(g_pos,&gdata);*/
				getGdataDisplayed(&gdata);
				if(gdata != NULL) {
					set(app,MUIA_Application_Sleep,TRUE);

					mdata = new MessageListData();
					mdata->init();
					mdata->flags[0]=FALSE;
					mdata->flags[2]=FALSE;
					mdata->flags[6]=-1;

					char *header = new char[10240];
					char *hptr = header;

					int r = 0;
					strcpy(mdata->from,"Joined Message");
					r = sprintf(hptr,"From: %s\n",mdata->from); hptr += r;

					char date[256] = "";
					DateHandler::get_datenow(date,getGMTOffset(),account.bst);
					DateHandler::read_date(&mdata->ds,date,mdata->c_date,mdata->c_time);
					r = sprintf(hptr,"Date: %s\n",date); hptr += r;

					strncpy(mdata->subject,getstr(STR_joinmsgs_SUBJECT),IHEADENDSUBJECT);
					mdata->subject[IHEADENDSUBJECT] = '\0';
					r = sprintf(hptr,"Subject: %s\n",mdata->subject); hptr += r;
					nLog("subject: %s\n",mdata->subject);

					struct DateStamp ds;
					DateStamp(&ds);
					sprintf(mdata->messageID,"<joined_message_%d%d%d@null>",ds.ds_Days,ds.ds_Minute,rand() % 65536);
					r = sprintf(hptr,"Message-ID: %s\n",mdata->messageID); hptr += r;

					strcpy(mdata->newsgroups,"None");
					r = sprintf(hptr,"Newsgroups: %s\n",mdata->newsgroups); hptr += r;

					r = sprintf(hptr,"Content-Type: text/plain;\n"); hptr += r;

					r = sprintf(hptr,"\n"); hptr += r;
					int headerlen = hptr - header;
					mdata->size = 0;

					char *big_buffer = new char[big_bufsize_g + 1];
					BPTR file = NULL;
					BOOL ok = FALSE;
					for(;;) {
						getFilePath(filename,gdata->ID,gdata->nextmID);
						if(!exists(filename) && (file=Open(filename,MODE_NEWFILE)) != NULL)
							break;
						gdata->nextmID++;
					}
					mdata->ID=gdata->nextmID;
					nLog("filename: %s\n",filename);
					nLog("nextmID %d\n",gdata->nextmID);
					nLog("     ID %d\n",mdata->ID);
					if(file) {
						Write(file,header,headerlen);
						mdata->size += headerlen;

						for(int i=0;i<entries;i++) {
							MessageListData *this_mdata = NULL;
 							DoMethod(NLIST_joinmsgs_MSGS,MUIM_NList_GetEntry,i,&this_mdata);

							char filename2[MAXFILENAME] = "";
							getFilePath(filename2,this_mdata->flags[6],this_mdata->ID);
							nLog("%d : %d : %d : %s\n",i,this_mdata->flags[6],this_mdata->ID,filename2);
							BPTR this_lock = Lock(filename2,ACCESS_READ);
							BPTR this_file = Open(filename2,MODE_OLDFILE);
							if(this_file != NULL) {
								BOOL more = TRUE;
								BOOL header = TRUE;
								for(;;) {
									if(!FGets(this_file,big_buffer,big_bufsize_g)) {
										more = FALSE;
										break;
									}
									StripNewLine(big_buffer);
									if(header && *big_buffer == '\0')
										header = FALSE;
									else if(!header && *big_buffer != '\0') {
										int len = strlen(big_buffer);
										Write(file,big_buffer,len);
										Write(file,"\n",1);
										mdata->size += len + 1;
										break;
									}
								}
								Flush(this_file);
								if(more) {
									for(;;) {
										//int read = Read(this_file,buffer,bufsize);
										int read = Read(this_file,big_buffer,big_bufsize_g);
										if(read <= 0)
											break;
										big_buffer[read] = '\0';
										Write(file,big_buffer,read);
										mdata->size += read;
									}
								}
								/*
								BOOL header = TRUE;
								BOOL body = FALSE;
								int n_nl = 0;
								for(;;) {
									if(!FGets(this_file,buffer,MAXLINE))
										break;
									StripNewLine(buffer);
									if(header && *buffer == '\0') {
										header = FALSE;
									}
									else if(!header) {
										if(*buffer == '\0') {
											if(body)
												n_nl++;
										}
										else {
											// line that is part of the body - write it out
											body = TRUE;
											if(n_nl > 0) {
												// write out newlines
												for(int j=0;j<n_nl;j++)
													Write(file,"\n",1);
												mdata->size += n_nl;
												n_nl = 0;
											}
											int len = strlen(buffer);
											Write(file,buffer,len);
											mdata->size+=len;
											Write(file,"\n",1);
											mdata->size++;
										}
									}
								}
								*/
								Close(this_file);
							}
							if(this_lock != NULL)
								UnLock(this_lock);
						}

						gdata->nextmID++;
						Close(file);
						file = NULL;
						ok = TRUE;

						write_index_single(gdata,mdata);
						setEnabled();
						//printf("subject: %s\n",mdata->subject);
						//printf("     ID %d\n",mdata->ID);
						gdata->nummess++;

						GroupData * gdata2 = NULL;
						getGdataDisplayed(&gdata2);
						if(gdata2->ID==gdata->ID)
							threadView();
						redrawGdataAll();
					}
					set(app,MUIA_Application_Sleep,FALSE);
					delete [] big_buffer;
					delete [] header;
				}
			}
			// no break
		}
		case JOINMSGS_CANCEL:
			set(wnd_joinmsgs,MUIA_Window_Open,FALSE);
			break;
		case ACC_PAGESIG:
			if(accountpage==FALSE) {
				int val = 0;
				get(pages_account,MUIA_Group_ActivePage,&val);
				if(val==ACCSIGPAGE) {
					if(sigs[0])
						DoMethod(ED_acc_SIG,MUIM_TextEditor_InsertText,sigs[0],0);
					accountpage=TRUE;
				}
			}
			break;
		case ACC_OKAY:
		{
			strcpy(account.name,getstr(STR_acc_NAME));
			strcpy(status_buffer_g,getstr(STR_acc_EMAIL));
			if(strchr(status_buffer_g,'@')==NULL || (strchr(status_buffer_g,'@')==&status_buffer_g[strlen(status_buffer_g)-1]))
				MUI_RequestA(app,0,0,"Program Settings","_Okay","\33cYou must enter an email\naddress in the form:\n  user@domain\n",0);
			else
				strcpy(account.email,getstr(STR_acc_EMAIL));

			strcpy(status_buffer_g,getstr(STR_acc_REALEMAIL));
			if( (strchr(status_buffer_g,'@')==NULL || (strchr(status_buffer_g,'@')==&status_buffer_g[strlen(status_buffer_g)-1])) && *status_buffer_g!=0)
				MUI_RequestA(app,0,0,"Program Settings","_Okay","\33cYou must enter an email\naddress in the form:\n  user@domain\n",0);
			else
				strcpy(account.realemail,getstr(STR_acc_REALEMAIL));
			
			strcpy(account.org,getstr(STR_acc_ORG));

			strcpy(account.smtp,getstr(STR_acc_SMTP));
			strcpy(account.domain,getstr(STR_acc_DOMAIN));
			strcpy(account.followup_text,getstr(STR_acc_FOLLOWUPTEXT));
			strcpy(account.charset_write,getstr(STR_acc_CHARSETWRITE));
			get(CY_acc_TIMEZONE,MUIA_Cycle_Active,&account.timezone);
			account.timezone -= 12;
			get(CM_acc_USELOCALETZ,MUIA_Selected,&account.uselocaletz);
			get(CM_acc_BST,MUIA_Selected,&account.bst);
			get(CY_acc_DATEFORMAT,MUIA_Cycle_Active,&account.dateformat);

			account.flags = 0;

			int val = 0;
			get(CM_acc_SNIPSIG,MUIA_Selected,&val);
			account.flags = account.flags | Account::SNIPSIG;
			if(!val)
				account.flags -= Account::SNIPSIG;

			get(CM_acc_LOGGING,MUIA_Selected,&val);
			account.flags = account.flags | Account::LOGGING;
			if(!val)
				account.flags -= Account::LOGGING;

			get(CM_acc_LOGDEL,MUIA_Selected,&val);
			account.flags = account.flags | Account::LOGDEL;
			if(!val)
				account.flags -= Account::LOGDEL;

			get(CM_acc_DELONLINE,MUIA_Selected,&val);
			account.flags = account.flags | Account::NODELONLINE;
			if(val) // reverse logic
				account.flags -= Account::NODELONLINE;

			get(CM_acc_CONFIRMQUIT,MUIA_Selected,&val);
			account.flags = account.flags | Account::NOCONFIRMQUIT;
			if(val) // reverse logic
				account.flags -= Account::NOCONFIRMQUIT;

			get(CM_acc_QUIETDL,MUIA_Selected,&val);
			if(val) account.flags |= Account::QUIETDL;

			get(CM_acc_CHECKFORDUPS,MUIA_Selected,&val);
			if(val) account.flags |= Account::CHECKFORDUPS;

			get(CM_acc_VGROUPDL,MUIA_Selected,&account.vgroupdl);
			get(CM_acc_NOCONFIRMDEL,MUIA_Selected,&account.noconfirmdel);
			get(CM_acc_XNEWS,MUIA_Selected,&account.xnews);
			//get(CM_acc_USESIG,MUIA_Selected,&account.usesig);
			strcpy(status_buffer_g,getstr(STR_acc_LINELENGTH));
			account.linelength = atoi(status_buffer_g);
			if(account.linelength<4)
				account.linelength=4;
			if(account.linelength<60 || account.linelength>80) {
				sprintf(status_buffer_g,"\33cA line length of %d is\nconsidered bad style;\nyou are advised to change to a value\nbetween 60 and 80!",account.linelength);
				MUI_RequestA(app,0,0,"Program Settings","_Okay",status_buffer_g,0);
			}
			get(CM_acc_REWRAP,MUIA_Selected,&val);
			if(val)
				account.rewrap = TRUE;
			else
				account.rewrap = FALSE;

			get(CY_acc_XNO,MUIA_Cycle_Active,&account.xno);
			if(accountpage) {
				if(sigs[cy_current_sig]) {
					delete [] sigs[cy_current_sig];
					sigs[cy_current_sig]=NULL;
				}
				sigs[cy_current_sig]=(STRPTR)DoMethod(ED_acc_SIG,MUIM_TextEditor_ExportText);
				// accountpage set to FALSE at end of ACC_CANCEL bit
			}

			account.listflags = 0;
			get(CM_acc_LISTFLAGS,MUIA_Selected,&val);
			if(val)
				account.listflags |= Account::LISTFLAGS;
			get(CM_acc_LISTFROMGROUP,MUIA_Selected,&val);
			if(val)
				account.listflags |= Account::LISTFROMGROUP;
			get(CM_acc_LISTDATE,MUIA_Selected,&val);
			if(val)
				account.listflags |= Account::LISTDATE;
			get(CM_acc_LISTSUBJECT,MUIA_Selected,&val);
			if(val)
				account.listflags |= Account::LISTSUBJECT;
			get(CM_acc_LISTSIZE,MUIA_Selected,&val);
			if(val)
				account.listflags |= Account::LISTSIZE;
			get(CM_acc_LISTLINES,MUIA_Selected,&val);
			if(val)
				account.listflags |= Account::LISTLINES;
			resetMessageListFormat();
			redrawMdataAll();
			DoMethod(NLIST_messagelistdata,MUIM_NList_ColWidth,MUIV_NList_ColWidth_All,MUIV_NList_ColWidth_Default);
			DoMethod(LISTTREE_messagelistdata,MUIM_NList_ColWidth,MUIV_NList_ColWidth_All,MUIV_NList_ColWidth_Default);
			DoMethod(NLIST_search_RES,MUIM_NList_Redraw,MUIV_NList_Redraw_All);
			DoMethod(NLIST_search_RES,MUIM_NList_ColWidth,MUIV_NList_ColWidth_All,MUIV_NList_ColWidth_Default);

			if(account.mimeprefsno>0) {
				for(int k=0;k<account.mimeprefsno;k++)
					delete account.mimeprefs[k];
			}
			get(NLIST_acc_MIMEPREFS,MUIA_NList_Entries,&val);
			if(val>0) {
				if(val>256)
					val=256;
				for(int k=0;k<val;k++) {
					DoMethod(NLIST_acc_MIMEPREFS,MUIM_NList_GetEntry,k,&ptr);
					account.mimeprefs[k]=new MIMEPrefs;
					*account.mimeprefs[k]=*(MIMEPrefs *)ptr;
				}
			}
			account.mimeprefsno=val;
			strcpy(account.defviewer,getstr(STR_acc_MIMEDEF));
			int result = 0;
			get(CY_acc_READHEADER,MUIA_Cycle_Active,&result);
			account.readheader_type=(int)result;
			strncpy(account.readheaders,getstr(STR_acc_READHEADER),READHEADER_LEN);
			account.readheaders[READHEADER_LEN] = '\0';
			get(PEN_acc_TEXT_QUOTE2,MUIA_Pendisplay_Spec,&ptr);
			account.pen_acc_text_quote2 = *((MUI_PenSpec *)ptr);
			get(PEN_acc_TEXT_COL,MUIA_Pendisplay_Spec,&ptr);
			account.pen_acc_text_col = *((MUI_PenSpec *)ptr);
			get(CM_acc_MULTIPLEVWS,MUIA_Selected,&account.multiplevws);
			account.save_data();
			save_servers();
			// no break
		}
		case ACC_CANCEL:
			get(PEN_acc_TEXT_QUOTE2,MUIA_Pendisplay_Spec,&ptr);
			if(ptr)
				delete ptr;
			get(PEN_acc_TEXT_COL,MUIA_Pendisplay_Spec,&ptr);
			if(ptr)
				delete ptr;
			set(wnd_account,MUIA_Window_Open,FALSE);
			/*if(returnID == ACC_CANCEL) { // needed cos no break in ACC_OKAY
				load_servers();
			}*/ // not done due to issues with changing article pointers
			set(STR_acc_NAME,MUIA_String_Contents,"");
			set(STR_acc_EMAIL,MUIA_String_Contents,"");
			set(STR_acc_REALEMAIL,MUIA_String_Contents,"");
			set(STR_acc_ORG,MUIA_String_Contents,"");
			set(STR_acc_NNTPPOST,MUIA_String_Contents,"");
			set(STR_acc_SMTP,MUIA_String_Contents,"");
			set(STR_acc_DOMAIN,MUIA_String_Contents,"");
			set(STR_acc_FOLLOWUPTEXT,MUIA_String_Contents,"");
			set(CM_acc_BST,MUIA_Selected,FALSE);
			set(CM_acc_VGROUPDL,MUIA_Selected,FALSE);
			set(CM_acc_DELONLINE,MUIA_Selected,TRUE);
			set(CM_acc_CONFIRMQUIT,MUIA_Selected,TRUE);
			set(CM_acc_QUIETDL,MUIA_Selected,FALSE);
			set(CM_acc_CHECKFORDUPS,MUIA_Selected,FALSE);
			set(CM_acc_NOCONFIRMDEL,MUIA_Selected,FALSE);
			set(CM_acc_XNEWS,MUIA_Selected,FALSE);
			//set(CM_acc_USESIG,MUIA_Selected,FALSE);
			DoMethod(ED_acc_SIG,MUIM_TextEditor_ClearText);
			DoMethod(NLIST_acc_MIMEPREFS,MUIM_NList_Clear);
			accountpage=FALSE;
			break;
		case ACC_ADDSERVER:
		{
			int val = 0;
			get(wnd_servers,MUIA_Window_Open,&val);
			if(val==FALSE) {
				set(STR_acc_NNTP,MUIA_String_Contents,"");
				set(STR_acc_PORT,MUIA_String_Contents,"119");
				set(STR_acc_USER,MUIA_String_Contents,"");
				set(STR_acc_PASS,MUIA_String_Contents,"");
				set(CM_acc_AUTH,MUIA_Selected,FALSE);
				set(wnd_servers,MUIA_Window_Open,TRUE);
			}
			else
				MUI_RequestA(app,0,0,"Add Server","_Okay","Please finish adding/editing the current server\nbefore adding a new one.",0);
			break;
		}
		case ACC_EDITSERVER:
		{
			int val = 0;
			get(wnd_servers,MUIA_Window_Open,&val);
			if(val==FALSE && editServer==NULL) {
				int val2 = 0;
				get(NLIST_acc_SERVERS,MUIA_NList_Active,&val2);
				if(val2!=MUIV_NList_Active_Off) {
					Server *server;
					DoMethod(NLIST_acc_SERVERS,MUIM_NList_GetEntry,val2,&server);
					set(STR_acc_NNTP,MUIA_String_Contents,server->nntp);
					set(STR_acc_PORT,MUIA_String_Integer,server->port);
					set(STR_acc_USER,MUIA_String_Contents,server->user);
					set(STR_acc_PASS,MUIA_String_Contents,server->password);
					set(CM_acc_AUTH,MUIA_Selected,server->nntp_auth);
					set(wnd_servers,MUIA_Window_Open,TRUE);
					editServer = server;
				}
			}
			else
				MUI_RequestA(app,0,0,"Edit Server","_Okay","Please finish adding/editing the current server\nbefore editing a new one.",0);
			break;
		}
		case ACC_MAKEDEFSERVER:
		{
			get(NLIST_acc_SERVERS,MUIA_NList_Entries,&entries);
			int val = 0;
			get(NLIST_acc_SERVERS,MUIA_NList_Active,&val);
			if(entries>0 && val!=MUIV_NList_Active_Off) {
				Server *server = NULL;
				int i=0;
				for(i=0;i<entries;i++) {
					DoMethod(NLIST_acc_SERVERS,MUIM_NList_GetEntry,i,&server);
					if(i==val)
						server->def=TRUE;
					else
						server->def=FALSE;
				}
				DoMethod(NLIST_acc_SERVERS,MUIM_NList_Redraw,MUIV_NList_Redraw_All);
				GroupData *active_gdata = NULL;
				getGdataActive(&active_gdata);
				// update article pointers for all default groups
				int result = MUI_RequestA(app,0,0,"Reset Article Pointers","_Reset|_Don't Reset","\33cYou have changed the default NNTP server, do you wish to reset the article pointer\nfor all groups using the default server?\n(see documentation for details - if unsure, you should Reset).",0);
				getGdataEntries(&entries);
				for(i=0;i<entries;i++) {
					getGdata(i,&gdata);
					if(gdata!=NULL) {
						if(gdata->serverID==0) {
							if(result == 1) {
								//printf("Reset for group: %s (%d)\n",gdata->name,gdata->serverID);
								resetArticlePointers(gdata);
							}
							if(gdata == active_gdata)
								setGdataHelpText(active_gdata); // update help bubble text, since using a different newsserver
						}
					}
				}
			}
			break;
		}
		case ACC_MAKEPOSTSERVER:
		{
			get(NLIST_acc_SERVERS,MUIA_NList_Entries,&entries);
			int val = 0;
			get(NLIST_acc_SERVERS,MUIA_NList_Active,&val);
			if(entries>0 && val!=MUIV_NList_Active_Off) {
				Server *server;
				for(int i=0;i<entries;i++) {
					DoMethod(NLIST_acc_SERVERS,MUIM_NList_GetEntry,i,&server);
					if(i==val)
						server->post=TRUE;
					else
						server->post=FALSE;
				}
				DoMethod(NLIST_acc_SERVERS,MUIM_NList_Redraw,MUIV_NList_Redraw_All);
			}
			break;
		}
		case ACC_DELETESERVER:
		{
			int val = 0;
			get(NLIST_acc_SERVERS,MUIA_NList_Active,&val);
			if(val!=MUIV_NList_Active_Off)
			{
				get(NLIST_acc_SERVERS,MUIA_NList_Entries,&entries);
				if(entries>1) {
					Server *server;
					DoMethod(NLIST_acc_SERVERS,MUIM_NList_GetEntry,val,&server);
					if(editServer!=server) {
						int result = MUI_RequestA(app,0,0,"Delete Server","_Delete|_Cancel","\33cAre you sure you wish\nto delete this server entry?",0);
						if(result == 1) {
							int def = server->def;
							int post = server->post;
							
							int reset = MUI_RequestA(app,0,0,"Reset Article Pointers","_Reset|_Don't Reset","\33cDo you wish to reset article pointers for any groups\nthat were using this server?\n(see documentation for details - if unsure, you should Reset).",0);
							getGdataEntries(&entries);
							GroupData *active_gdata = NULL;
							getGdataActive(&active_gdata);
							for(int i=0;i<entries;i++) {
								getGdata(i,&gdata);
								if(gdata!=NULL) {
									if( (gdata->serverID==0 && def==TRUE) || gdata->serverID==server->ID ) {
										if( reset == 1 ) {
											//printf("Reset for group: %s (%d)\n",gdata->name,gdata->serverID);
											resetArticlePointers(gdata);
										}
										if(gdata == active_gdata)
											setGdataHelpText(active_gdata); // update help bubble text, since using a different newsserver
									}
									if( gdata->serverID==server->ID ) {
										//printf("Set group to default: %s (%d)\n",gdata->name,gdata->serverID);
										gdata->serverID = 0;
									}
								}
							}

							DoMethod(NLIST_acc_SERVERS,MUIM_NList_Remove,val);
							if(def==TRUE) { // make another default
								DoMethod(NLIST_acc_SERVERS,MUIM_NList_GetEntry,0,&server);
								server->def=TRUE;
							}
							if(post==TRUE) { // make another the posting
								//DoMethod(NLIST_acc_SERVERS,MUIM_NList_GetEntry,0,&server);
								server = getDefaultServer();
								server->post=TRUE;
							}
							DoMethod(NLIST_acc_SERVERS,MUIM_NList_Redraw,MUIV_NList_Redraw_All);
						}
					}
					else
						MUI_RequestA(app,0,0,"Delete Server","_Okay","You cannot delete a server that is being edited!",0);
				}
				else
					MUI_RequestA(app,0,0,"Delete Server","_Okay","You cannot delete the last remaining server!",0);
			}
			break;
		}
		case SERVER_OKAY:
		{
			Server *server = new Server();
			strcpy(server->nntp,getstr(STR_acc_NNTP));
			strcpy(server->user,getstr(STR_acc_USER));
			strcpy(server->password,getstr(STR_acc_PASS));
			get(CM_acc_AUTH,MUIA_Selected,&server->nntp_auth);
			get(STR_acc_PORT,MUIA_String_Integer,&server->port);
			server->def = FALSE;
			server->post = FALSE;
			int changed = FALSE;
			if(editServer==NULL) {
				server->ID = nextServerID++;
				DoMethod(NLIST_acc_SERVERS,MUIM_NList_InsertSingle,server,MUIV_NList_Insert_Bottom);
			}
			else {
				if(stricmp(editServer->nntp,server->nntp)!=0)
					changed = TRUE;
				server->ID = editServer->ID;
				server->def = editServer->def;
				server->post = editServer->post;
				int pos=-1;
				get(NLIST_acc_SERVERS,MUIA_NList_Entries,&entries);
				Server *server2;
				for(int i=0;i<entries;i++) {
					DoMethod(NLIST_acc_SERVERS,MUIM_NList_GetEntry,i,&server2);
					if(server2==editServer) {
						pos = i;
						break;
					}
				}
				if(pos==-1) // not found! (this shouldn't happen..)
					DoMethod(NLIST_acc_SERVERS,MUIM_NList_InsertSingle,server,MUIV_NList_Insert_Bottom);
				else
					DoMethod(NLIST_acc_SERVERS,MUIM_NList_ReplaceSingle,server,pos,NOWRAP,ALIGN_LEFT);
			}
			if(changed) {
				int result = MUI_RequestA(app,0,0,"Reset Article Pointers","_Reset|_Don't Reset","\33cYou have changed this server's address.\nDo you wish to reset article pointers for any groups\nthat were using this server?\n(see documentation for details - if unsure, you should Reset).",0);
				GroupData *active_gdata = NULL;
				getGdataActive(&active_gdata);

				getGdataEntries(&entries);
				for(int i=0;i<entries;i++) {
					getGdata(i,&gdata);
					if(gdata!=NULL) {
						if( (gdata->serverID==0 && server->def==TRUE) || gdata->serverID==server->ID ) {
							if(result == 1) {
								//printf("Reset for group: %s (%d)\n",gdata->name,gdata->serverID);
								resetArticlePointers(gdata);
							}
							if(gdata == active_gdata)
								setGdataHelpText(active_gdata); // update help bubble text, since using a different newsserver
						}
					}
				}
			}
			DoMethod(NLIST_acc_SERVERS,MUIM_NList_Redraw,MUIV_NList_Redraw_All);
			// no break
		}
		case SERVER_CANCEL:
			editServer = NULL;
			set(wnd_servers,MUIA_Window_Open,FALSE);
			break;
		case ACC_CYSIG:
			if(accountpage)
			{
				int val = 0;
				get(CY_acc_SIG,MUIA_Cycle_Active,&val);
				if(sigs[cy_current_sig]) {
					delete [] sigs[cy_current_sig];
					sigs[cy_current_sig]=NULL;
				}
				char *sig = (char *)DoMethod(ED_acc_SIG,MUIM_TextEditor_ExportText);
				sigs[cy_current_sig] = new char[ strlen(sig) + 1 ];
				strcpy(sigs[cy_current_sig],sig);
				FreeVec(sig);
				sig = NULL;
				cy_current_sig=val;
				DoMethod(ED_acc_SIG,MUIM_TextEditor_ClearText);
				if(sigs[val])
					DoMethod(ED_acc_SIG,MUIM_TextEditor_InsertText,sigs[val],MUIV_TextEditor_InsertText_Top);
			}
			break;
		case ACC_READSIG:
		{
			sleepAll(TRUE);
			BOOL ok = LoadASL(filename,"Select File to Read in","","#?",FALSE);
			sleepAll(FALSE);
			if(ok)
				readInText(ED_acc_SIG,filename);
			break;
		}
		case ACC_STRKILL:
		case ACC_STRKILLTEMP:
		{
			ptr=(KillFile *)new KillFile();
			int val = 0;
			get(NLIST_acc_KILLFILE,MUIA_NList_Active,&val);
			if(val!=MUIV_NList_Active_Off || returnID!=ACC_STRKILLTEMP) { // clicking cycle on blank shouldn't do anything here..
				if(val!=MUIV_NList_Active_Off) {
					DoMethod(NLIST_acc_KILLFILE,MUIM_NList_GetEntry,MUIV_NList_GetEntry_Active,&ptr2);
					*((KillFile *)ptr)=*((KillFile *)ptr2);
				}
				strcpy(((KillFile *)ptr)->header,getstr(STR_acc_NEWKILLHEAD));
				strcpy(((KillFile *)ptr)->text,getstr(STR_acc_NEWKILLTEXT));
				strcpy(((KillFile *)ptr)->ngroups,getstr(STR_acc_NEWKILLGROUP));
				if(strlen(((KillFile *)ptr)->header)==0 && strlen(((KillFile *)ptr)->text)==0 && strlen(((KillFile *)ptr)->ngroups)==0) {
					// oops we don't want blank entries!
					delete ptr;
					ptr=NULL;
				}
				else {
					get(CY_acc_EXPIREKILL,MUIA_Cycle_Active,&((KillFile *)ptr)->expiretype);
					strcpy(status_buffer_g,getstr(STR_acc_EXPIREKILL));
					((KillFile *)ptr)->expire = atoi(status_buffer_g);
					account.defexpiretype=((KillFile *)ptr)->expiretype;
					account.defexpire=((KillFile *)ptr)->expire;

					/*get(CY_acc_TYPEKILL,MUIA_Cycle_Active,&val2);
					((KillFile *)ptr)->type = val2;*/
					int val2 = 0;
					get(CY_acc_MATCHKILL,MUIA_Cycle_Active,&val2);
					((KillFile *)ptr)->match = val2;
					get(CY_acc_ACTIONKILL,MUIA_Cycle_Active,&val2);
					((KillFile *)ptr)->action = val2;
					get(CM_acc_SKIPKILL,MUIA_Selected,&val2);
					((KillFile *)ptr)->carryon = val2 ? 0 : 1;

					val2 = strlen( ((KillFile *)ptr)->header ); // add colon if not there and not blank
					if(val2>0) {
						if( ((KillFile *)ptr)->header[val2-1] != ':') {
							((KillFile *)ptr)->header[val2]=':';
							((KillFile *)ptr)->header[val2+1]=0;
						}
					}
					get(NLIST_acc_KILLFILE,MUIA_NList_Active,&val);
					// convert to upper case
					toUpper(((KillFile *)ptr)->header);
					toUpper(((KillFile *)ptr)->text);
					toUpper(((KillFile *)ptr)->ngroups);
					if(val==MUIV_NList_Active_Off) {
						DoMethod(NLIST_acc_KILLFILE,MUIM_NList_InsertSingle,ptr,MUIV_NList_Insert_Bottom);
						set(wnd_account,MUIA_Window_ActiveObject,STR_acc_NEWKILLHEAD);
					}
					else
						DoMethod(NLIST_acc_KILLFILE,MUIM_NList_ReplaceSingle,ptr,val,NOWRAP,ALIGN_LEFT);
					if(returnID==ACC_STRKILL) { // so STRKILLTEMP, generated by cycle gadget changing, doesn't clear the entries
						set(STR_acc_NEWKILLHEAD,MUIA_String_Contents,"");
						set(STR_acc_NEWKILLTEXT,MUIA_String_Contents,"");
						set(STR_acc_NEWKILLGROUP,MUIA_String_Contents,"");
						set(CY_acc_EXPIREKILL,MUIA_Cycle_Active,0);
						set(STR_acc_EXPIREKILL,MUIA_String_Contents,"");
						//set(CY_acc_TYPEKILL,MUIA_Cycle_Active,0);
						set(CY_acc_MATCHKILL,MUIA_Cycle_Active,0);
						set(CY_acc_ACTIONKILL,MUIA_Cycle_Active,0);
						set(CM_acc_SKIPKILL,MUIA_Selected,TRUE);
						set(NLIST_acc_KILLFILE,MUIA_NList_Active,MUIV_NList_Active_Off);
					}
				}
			}
			break;
		}
		case ACC_KILLCHANGED:
		{
			int val = 0;
			get(NLIST_acc_KILLFILE,MUIA_NList_Active,&val);
			if(val!=MUIV_NList_Active_Off)
			{
				DoMethod(NLIST_acc_KILLFILE,MUIM_NList_GetEntry,MUIV_NList_GetEntry_Active,&ptr);
				set(STR_acc_NEWKILLHEAD,MUIA_String_Contents,((KillFile *)ptr)->header);
				set(STR_acc_NEWKILLTEXT,MUIA_String_Contents,((KillFile *)ptr)->text);
				set(STR_acc_NEWKILLGROUP,MUIA_String_Contents,((KillFile *)ptr)->ngroups);
				set(CY_acc_EXPIREKILL,MUIA_Cycle_Active,((KillFile *)ptr)->expiretype);
				sprintf(status_buffer_g,"%d",((KillFile *)ptr)->expire);
				set(STR_acc_EXPIREKILL,MUIA_String_Contents,status_buffer_g);
				//set(CY_acc_TYPEKILL,MUIA_Cycle_Active,(int)((KillFile *)ptr)->type);
				set(CY_acc_MATCHKILL,MUIA_Cycle_Active,(int)((KillFile *)ptr)->match);
				set(CY_acc_ACTIONKILL,MUIA_Cycle_Active,(int)((KillFile *)ptr)->action);
				set(CM_acc_SKIPKILL,MUIA_Selected,(((KillFile *)ptr)->carryon ? FALSE : TRUE));
			}
			else
			{
				set(STR_acc_NEWKILLHEAD,MUIA_String_Contents,"");
				set(STR_acc_NEWKILLTEXT,MUIA_String_Contents,"");
				set(STR_acc_NEWKILLGROUP,MUIA_String_Contents,"");
				set(CY_acc_EXPIREKILL,MUIA_Cycle_Active,0);
				set(STR_acc_EXPIREKILL,MUIA_String_Contents,"");
				//set(CY_acc_TYPEKILL,MUIA_Cycle_Active,0);
				set(CY_acc_MATCHKILL,MUIA_Cycle_Active,0);
				set(CY_acc_ACTIONKILL,MUIA_Cycle_Active,0);
				set(CM_acc_SKIPKILL,MUIA_Selected,TRUE);
			}
			set(wnd_account,MUIA_Window_ActiveObject,STR_acc_NEWKILLHEAD);
			break;
		}
		case ACC_NEWKILL:
			set(STR_acc_NEWKILLHEAD,MUIA_String_Contents,"");
			set(STR_acc_NEWKILLTEXT,MUIA_String_Contents,"");
			set(STR_acc_NEWKILLGROUP,MUIA_String_Contents,"");
			set(CY_acc_EXPIREKILL,MUIA_Cycle_Active,account.defexpiretype);
			set(STR_acc_EXPIREKILL,MUIA_String_Integer,account.defexpire);
			//set(CY_acc_TYPEKILL,MUIA_Cycle_Active,0);
			set(CY_acc_MATCHKILL,MUIA_Cycle_Active,0);
			set(CY_acc_ACTIONKILL,MUIA_Cycle_Active,0);
			set(CM_acc_SKIPKILL,MUIA_Selected,TRUE);
			set(NLIST_acc_KILLFILE,MUIA_NList_Active,MUIV_NList_Active_Off);
			set(wnd_account,MUIA_Window_ActiveObject,STR_acc_NEWKILLHEAD);
			break;
		case ACC_DELKILL:
		{
			int val = 0;
			get(NLIST_acc_KILLFILE,MUIA_NList_Active,&val);
			if(val!=MUIV_NList_Active_Off)
			{
				int result = MUI_RequestA(app,0,0,"Delete Killfile Entry","_Delete|_Cancel","\33cAre you sure you wish\nto delete this killfile entry?",0);
				if(result==1)
				{
					DoMethod(NLIST_acc_KILLFILE,MUIM_NList_Remove,val);
					set(STR_acc_NEWKILLHEAD,MUIA_String_Contents,"");
					set(STR_acc_NEWKILLTEXT,MUIA_String_Contents,"");
					set(STR_acc_NEWKILLGROUP,MUIA_String_Contents,"");
					set(CY_acc_EXPIREKILL,MUIA_Cycle_Active,0);
					set(STR_acc_EXPIREKILL,MUIA_String_Contents,"");
					//set(CY_acc_TYPEKILL,MUIA_Cycle_Active,0);
					set(CY_acc_MATCHKILL,MUIA_Cycle_Active,0);
					set(CY_acc_ACTIONKILL,MUIA_Cycle_Active,0);
					set(CM_acc_SKIPKILL,MUIA_Selected,TRUE);
					set(wnd_account,MUIA_Window_ActiveObject,STR_acc_NEWKILLHEAD);
				}
			}
			break;
		}
		case ACC_DUPKILL:
		{
			int val = 0;
			get(NLIST_acc_KILLFILE,MUIA_NList_Active,&val);
			if(val!=MUIV_NList_Active_Off)
			{
				DoMethod(NLIST_acc_KILLFILE,MUIM_NList_GetEntry,MUIV_NList_GetEntry_Active,&ptr);
				ptr2=(KillFile *)new KillFile();
				*((KillFile *)ptr2)=*((KillFile *)ptr);
				// not an identical copy, since we have new creation and lastused dates
				DateStamp(&((KillFile *)ptr2)->ds);
				DateStamp(&((KillFile *)ptr2)->lastused);
				DoMethod(NLIST_acc_KILLFILE,MUIM_NList_InsertSingle,ptr2,MUIV_NList_Insert_Active);
			}
			break;
		}
		case ACC_MIMENEW:
			ptr=(MIMEPrefs *)new MIMEPrefs;
			strcpy(((MIMEPrefs *)ptr)->type,"text/plain");
			strcpy(((MIMEPrefs *)ptr)->viewer,"SYS:Utilities/Multiview \"%s\"");
			DoMethod(NLIST_acc_MIMEPREFS,MUIM_NList_InsertSingle,ptr,MUIV_NList_Insert_Bottom);
			set(NLIST_acc_MIMEPREFS,MUIA_NList_Active,MUIV_NList_Active_Bottom);
			set(STR_acc_MIME,MUIA_String_Contents,((MIMEPrefs *)ptr)->type);
			set(STR_acc_MIMEVIEW,MUIA_String_Contents,((MIMEPrefs *)ptr)->viewer);
			break;
		case ACC_MIMEDEL:
 			/*DoMethod(NLIST_acc_MIMEPREFS,MUIM_NList_GetEntry,MUIV_NList_GetEntry_Active,&ptr);
 			if(ptr)
 				delete ptr;*/
			DoMethod(NLIST_acc_MIMEPREFS,MUIM_NList_Remove,MUIV_NList_Remove_Active);
			break;
		case ACC_MIMECLICK:
			DoMethod(NLIST_acc_MIMEPREFS,MUIM_NList_GetEntry,MUIV_NList_GetEntry_Active,&ptr);
			if(ptr)
			{
				set(STR_acc_MIME,MUIA_String_Contents,((MIMEPrefs *)ptr)->type);
				set(STR_acc_MIMEVIEW,MUIA_String_Contents,((MIMEPrefs *)ptr)->viewer);
			}
			break;
		case ACC_MIMESTR:
		{
			int val = 0;
			get(NLIST_acc_MIMEPREFS,MUIA_NList_Active,&val);
			ptr = new MIMEPrefs;
			strcpy(((MIMEPrefs *)ptr)->type,getstr(STR_acc_MIME));
			strcpy(((MIMEPrefs *)ptr)->viewer,getstr(STR_acc_MIMEVIEW));
			if( *((MIMEPrefs *)ptr)->type==0 && *((MIMEPrefs *)ptr)->viewer==0 )
				delete ptr;
			else
			{
				if(val==MUIV_NList_Active_Off)
					DoMethod(NLIST_acc_MIMEPREFS,MUIM_NList_InsertSingle,ptr,MUIV_NList_Insert_Bottom);
				else
					DoMethod(NLIST_acc_MIMEPREFS,MUIM_NList_ReplaceSingle,ptr,val,NOWRAP,ALIGN_LEFT);
				set(STR_acc_MIME,MUIA_String_Contents,"");
				set(STR_acc_MIMEVIEW,MUIA_String_Contents,"");
			}
			set(NLIST_acc_MIMEPREFS,MUIA_NList_Active,MUIV_NList_Active_Off);
			break;
		}
		case KILL_CLOSE:
			//if(!downloading_headers) {
				set(wnd_killfile,MUIA_Window_Open,FALSE);
				get(CM_acc_SIZEKILL,MUIA_Selected,&account.use_sizekill);
				save_killfile();
			/*}
			else
				MUI_RequestA(app,0,0,"Save Killfile","_Okay","\33cPlease wait for downloading to finish first.",0);*/
			break;
		case CHOICE_SAVE:
			t_save=TRUE;
			break;
		case CHOICE_DISP:
			t_disp=TRUE;
			break;
		case CHOICE_CANC:
			t_abort=TRUE;
			break;
		case GROUPMAN_SUB:
			// copied & modified from newnewsgroup!
			DoMethod(NLIST_groupman,MUIM_NList_GetEntry,MUIV_NList_GetEntry_Active,&temp);
			wordFirst(status_buffer_g,temp);
			set(STR_nng_NAME,MUIA_String_Contents,status_buffer_g);
			set(wnd_newnewsgroup,MUIA_Window_Open,TRUE);
			set(wnd_newnewsgroup,MUIA_Window_ActiveObject,STR_nng_NAME);
			nng_defserver = groupman_server->ID;
			break;
		case GROUPMAN_FIND:
		{
			int val = 0;
			int val2 = 0;
			get(NLIST_groupman,MUIA_NList_Entries,&val);
			get(NLIST_groupman,MUIA_NList_Active,&val2);
			strcpy(status_buffer_g,getstr(STR_groupman_FIND));
			yesno=FALSE;
			if(val>0 && val2>=0 && val2+1<val) {
				for(int k=val2+1;k<val;k++) {
					DoMethod(NLIST_groupman,MUIM_NList_GetEntry,k,&temp);
					if(strstr(temp,status_buffer_g)) {
						set(NLIST_groupman,MUIA_NList_Active,k);
						yesno=TRUE;
						break;
					}
				}
			}
			if(!yesno)
				MUI_RequestA(app,0,0,"Group Manager","_Okay","\33cGroup not found!",0);
			break;
		}
		/*case GROUPMAN_SORT:
			DoMethod(NLIST_groupman,MUIM_NList_Sort);
			break;*/
		/*case GROUPMAN_WRITE:
			if(groupman_server != NULL) {
				result=MUI_RequestA(app,0,0,"Write List","_Write|_Cancel","\33cAre you sure you wish\nto write the grouplist?\n(May take some time)",0);
				if(result==1)
					writegrouplist(groupman_server);
			}
			break;*/
		case GROUPMAN_CLOSE:
			set(wnd_groupman,MUIA_Window_Open,FALSE);
			DoMethod(NLIST_groupman,MUIM_NList_Clear); // needed to free up memory
			break;
		case SEARCH_START:
			if(delete_dis)
				MUI_RequestA(app,0,0,"Not Available","_Okay","\33cThis function not available whilst\nNewsCoaster is connected with the newsserver!",0);
			else
			{
			get(NLIST_search_NG,MUIA_NList_Entries,&entries);
			DoMethod(NLIST_search_RES,MUIM_NList_Clear);
			if(entries>0) {
				MUI_NList_GetSelectInfo info;
				DoMethod(NLIST_search_NG,MUIM_NList_GetSelectInfo,&info);
				int n_selected = info.vnum;
				if(n_selected == 0) {
					MUI_RequestA(app,0,0,"Search Groups","_Okay","\33cPlease select some groups.",0);
				}
				else
				{
				int where = 0;
				char head[256] = "",what[256] = "";
				int casesens = 0;
				get(CY_search_WHERE,MUIA_Cycle_Active,&where);
				strcpy(head,getstr(STR_search_HEAD));
				strcpy(what,getstr(STR_search_WHAT));
				get(CM_search_CASESENS,MUIA_Selected,&casesens);
				if(casesens==FALSE)
					toUpper(what);
				sleepAll(TRUE);
				StatusWindow *statusWindow = new StatusWindow(app,"Searching..");
				BOOL aborted = FALSE;
				for(int k=0;k<entries && !aborted;k++) {
					LONG sel = 0;
					DoMethod(NLIST_search_NG,MUIM_NList_Select,k,MUIV_NList_Select_Ask,&sel);
					if(sel==MUIV_NList_Select_On) {
						DoMethod(NLIST_search_NG,MUIM_NList_GetEntry,k,&gdata);
						if(gdata) {
							sprintf(status_buffer_g,"Searching: %s",gdata->name);
							char *bufptr = &status_buffer_g[ strlen(status_buffer_g) ];
							statusWindow->setText(status_buffer_g);
							Vector * vector = new Vector(2048);
							read_index(gdata,vector);
							int entries2 = vector->getSize();
							MessageListData ** mdataptr = (MessageListData **)vector->getData();
							for(int l=0;l<entries2;l++) {
								DoMethod(app,MUIM_Application_InputBuffered);
								if(l % 16 == 0) {
									do_input();
									if(statusWindow->isAborted()==TRUE || running==FALSE) {
										aborted = TRUE;
										break;
									}
									sprintf(bufptr," ( %d / %d )",l,entries2);
									statusWindow->setText(status_buffer_g);
								}
								mdata = mdataptr[l];
								BOOL found=FALSE;
								//if(where < SEARCH_HEADER) { // quick version
								if(
									where == SEARCH_FROM ||
									where == SEARCH_NEWSGROUPS ||
									where == SEARCH_SUBJECT ||
									where == SEARCH_MESSAGEID
									) { // quick version
									if(casesens) {
										switch(where) {
											case SEARCH_FROM:
												if( strstr(mdata->from,what) )
													found=TRUE;
												break;
											case SEARCH_NEWSGROUPS:
											{
												char newsgroups[MAXLINE] = "";
												get_newsgroups(newsgroups,gdata->ID,mdata->ID);
												if( strstr(newsgroups,what) )
												//if( strstr(mdata->newsgroups,what) )
													found=TRUE;
												break;
											}
											case SEARCH_SUBJECT:
												if( strstr(mdata->subject,what) )
													found=TRUE;
												break;
											case SEARCH_MESSAGEID:
												if( strstr(mdata->messageID,what) )
													found=TRUE;
												break;
											/*case SEARCH_CONTENTTYPE:
												if( strstr(mdata->type,what) )
													found=TRUE;
												break;*/
										}
									}
									else {
										switch(where) {
											case SEARCH_FROM:
												if( stristr_q(mdata->from,what) )
													found=TRUE;
												break;
											case SEARCH_NEWSGROUPS:
											{
												char newsgroups[MAXLINE] = "";
												get_newsgroups(newsgroups,gdata->ID,mdata->ID);
												if( stristr_q(newsgroups,what) )
												//if( stristr_q(mdata->newsgroups,what) )
													found=TRUE;
												break;
											}
											case SEARCH_SUBJECT:
												if( stristr_q(mdata->subject,what) )
													found=TRUE;
												break;
											case SEARCH_MESSAGEID:
												if( stristr_q(mdata->messageID,what) )
													found=TRUE;
												break;
											/*case SEARCH_CONTENTTYPE:
												if( stristr_q(mdata->type,what) )
													found=TRUE;
												break;*/
										}
									}
								}
								else {
									if(casesens)
										found = search_mess(gdata,mdata,what,casesens,where);
									else
										found = search_mess(gdata,mdata,what,casesens,where);
								}
								if(found) {
									MessageListData * mdata2 = new MessageListData();
									*mdata2 = *mdata;
									mdata2->flags[6] = gdata->ID;
									DoMethod(NLIST_search_RES,MUIM_NList_InsertSingle,mdata2,MUIV_NList_Insert_Bottom);
								}
							}
							
							for(int i=0;i<vector->getSize();i++)
								delete vector->getData()[i];
							delete vector;
						}
					}
				}
				/*if(whatU)
					delete whatU;*/
				/*set(wnd_main,MUIA_Window_Sleep,FALSE);
				WriteWindow::sleepAll(FALSE);
				set(wnd_search,MUIA_Window_Sleep,FALSE);*/
				sleepAll(FALSE);
				delete statusWindow;
				}
			}
			}
			break;
		case SEARCH_MESSAGE:
		{
			int result = 0;
			get(NLIST_search_RES,MUIA_NList_Active,&result);
			if(result!=MUIV_NList_Active_Off) {
				DoMethod(NLIST_search_RES,MUIM_NList_GetEntry,MUIV_NList_GetEntry_Active,&mdata);
				int gID = mdata->flags[6];
				set(wnd_search,MUIA_Window_Sleep,TRUE);
				// now make sure we get an up to date copy of it!
				NewMessage newmess;
				get_refs(&newmess,gID,mdata->ID,GETREFS_LAST);
				newmess.copyToMessageListData(mdata);
				mdata->flags[6] = gID;
				ViewWindow *vw = NULL;
				if(ViewWindow::ptrs->getSize()==0 || account.multiplevws==TRUE)
					vw = new ViewWindow("NewsCoaster");
				else
					vw = ((ViewWindow **)ViewWindow::ptrs->getData())[0];
				//printf(":%d %d\n",gID,mdata->ID);
				vw->resetSingle(gID,mdata->ID);
				if(!vw->read())
					delete vw;
				set(wnd_search,MUIA_Window_Sleep,FALSE);
			}
			break;
		}
		case SEARCH_SORT:
		{
			int val = 0;
			get(NLIST_search_RES,MUIA_NList_TitleClick,&val);
			int icol = getInternalColumn(val);
			int sorttype = 0;
			//getGdataDisplayed(&gdata);
			if(getSortType(&sorttype,icol,0)) {
				if(sorttype_search == sorttype)
					sorttypedir_search = -sorttypedir_search;
				else {
					sorttype_search = sorttype;
					sorttypedir_search = 1;
				}
				//printf("%d %d %d\n",val,icol,sorttype_stats);
				set(wnd_search,MUIA_Window_Sleep,TRUE);
				DoMethod(NLIST_search_RES,MUIM_NList_Sort);
				set(wnd_search,MUIA_Window_Sleep,FALSE);
			}
			break;
		}
		case STATS_START:
		{
			if(delete_dis)
				MUI_RequestA(app,0,0,"Not Available","_Okay","\33cThis function not available whilst\nNewsCoaster is connected with the newsserver!",0);
			else {
			StatsList * statsList=NULL;
			get(NLIST_stats_NG,MUIA_NList_Entries,&entries);
			DoMethod(NLIST_stats_RES,MUIM_NList_Clear);
			if(entries>0) {
				MUI_NList_GetSelectInfo info;
				DoMethod(NLIST_stats_NG,MUIM_NList_GetSelectInfo,&info);
				int n_selected = info.vnum;
				if(n_selected == 0) {
					MUI_RequestA(app,0,0,"Statistics","_Okay","\33cPlease select some groups.",0);
				}
				else
				{
				int what = 0;
				get(CY_stats_WHAT,MUIA_Cycle_Active,&what);
				stats_what = what;
				set(wnd_main,MUIA_Window_Sleep,TRUE);
				WriteWindow::sleepAll(TRUE);
				set(wnd_stats,MUIA_Window_Sleep,TRUE);
				StatusWindow *statusWindow = new StatusWindow(app,"Scanning..");
				BOOL aborted = FALSE;
				for(int k=0;k<entries && !aborted;k++) {
					LONG sel = 0;
					DoMethod(NLIST_stats_NG,MUIM_NList_Select,k,MUIV_NList_Select_Ask,&sel);
					if(sel==MUIV_NList_Select_On) {
						DoMethod(NLIST_stats_NG,MUIM_NList_GetEntry,k,&gdata);
						if(gdata) {
							char * cmp = NULL;
							NewMessage newmessageTemp;
							char unknown[] = "Unknown";
							sprintf(status_buffer_g,"Scanning: %s",gdata->name);
							char *bufptr = &status_buffer_g[ strlen(status_buffer_g) ];
							statusWindow->setText(status_buffer_g);
							Vector * vector = new Vector(2048);
							read_index(gdata,vector);
							int entries2 = vector->getSize();
							MessageListData ** mdataptr = (MessageListData **)vector->getData();
							for(int l=0;l<entries2;l++) {
								DoMethod(app,MUIM_Application_InputBuffered);
								if(l % 16 == 0) {
									do_input();
									if(statusWindow->isAborted()==TRUE || running==FALSE) {
										aborted = TRUE;
										break;
									}
									sprintf(bufptr," ( %d / %d )",l,entries2);
									statusWindow->setText(status_buffer_g);
								}
								mdata = mdataptr[l];
								//nLog("Stats: (%d) %s\n",mdata->ID,mdata->subject);
								// see if an entry for this already exists in our list
								int entries3 = 0;
								get(NLIST_stats_RES,MUIA_NList_Entries,&entries3);
								if(what==0)
									cmp=mdata->from;
								else if(what==1) {
									cmp=mdata->subject;
									while(*cmp!=0 && (strincmp_q(cmp,"RE: ",4)==0 || strincmp_q(cmp,"SV: ",4)==0))
										cmp += 4;
								}
								else if(what==2) {
									get_refs(&newmessageTemp,gdata,mdata,GETREFS_NONE);
									if(*newmessageTemp.xnewsreader == '\0')
										cmp = unknown;
									else
										cmp = newmessageTemp.xnewsreader;
								}
								BOOL found=FALSE;
								for(int m=0;m<entries3;m++) {
									DoMethod(NLIST_stats_RES,MUIM_NList_GetEntry,m,&statsList);
									if(strcmp(cmp,statsList->value)==0) {
										found=TRUE;
										// insert new frequency value here
										statsList->freq++;
										DoMethod(NLIST_stats_RES,MUIM_NList_Redraw,m);
										break;
									}
								}
								if(!found) { // insert a new entry
									statsList = new StatsList;
									strcpy(statsList->value,cmp);
									statsList->freq=1;
									DoMethod(NLIST_stats_RES,MUIM_NList_InsertSingle,statsList,MUIV_NList_Insert_Bottom);
								}
							}
							for(int i=0;i<vector->getSize();i++)
								delete vector->getData()[i];
							delete vector;
						}
					}
				}
				set(wnd_main,MUIA_Window_Sleep,FALSE);
				WriteWindow::sleepAll(FALSE);
				set(wnd_stats,MUIA_Window_Sleep,FALSE);
				delete statusWindow;
				}
			}
			}
			break;
		}
		case STATS_SORT:
		{
			int val = 0;
			get(NLIST_stats_RES,MUIA_NList_TitleClick,&val);
			if(val==sorttype_stats)
				sorttypedir_stats = -sorttypedir_stats;
			else {
				sorttype_stats = val;
				sorttypedir_stats = 1;
			}
			set(wnd_stats,MUIA_Window_Sleep,TRUE);
			DoMethod(NLIST_stats_RES,MUIM_NList_Sort);
			set(wnd_stats,MUIA_Window_Sleep,FALSE);
			break;
		}
	}
	return TRUE;
}

//ASM ULONG TextEditor_Dispatcher (register __a0 struct IClass *cl, register __a2 Object *obj, register __a1 Msg msg)
/*ASM ULONG TextEditor_Dispatcher (REG(a0) struct IClass *cl,REG(a2) Object *obj,REG(a1) struct MUIP_TextEditor_HandleError *msg) {*/
ULONG HOOK3( TextEditor_Dispatcher, IClass *, cl, a0, Object *, obj, a2, MUIP_TextEditor_HandleError *, msg, a1 )
	MUIP_DragDrop *drop_msg=NULL;
	switch(msg->MethodID)
	{
		/*case MUIM_Show:
			break;
		case MUIM_Hide:
			break;*/
		case MUIM_DragQuery:
			return FALSE;
			break;
		/*case MUIM_DragDrop:
			drop_msg = (MUIP_DragDrop *)msg;
			ULONG active;
			if(GetAttr(MUIA_List_Active, drop_msg->obj, &active))
				DoMethod(obj, MUIM_TextEditor_InsertText, StdEntries[active]);
			break;*/
		case MUIM_TextEditor_HandleError:
			char *errortxt = NULL;
			switch(msg->errorcode) {
				case Error_ClipboardIsEmpty:
					errortxt = "\33cThe clipboard is empty.";
					break;
				case Error_ClipboardIsNotFTXT:
					errortxt = "\33cThe clipboard does not contain text.";
					break;
				case Error_MacroBufferIsFull:
					break;
				case Error_MemoryAllocationFailed:
					break;
				case Error_NoAreaMarked:
					errortxt = "\33cNo area marked.";
					break;
				case Error_NoMacroDefined:
					break;
				case Error_NothingToRedo:
					errortxt = "\33cNothing to redo.";
					break;
				case Error_NothingToUndo:
					errortxt = "\33cNothing to undo.";
					break;
				case Error_NotEnoughUndoMem:
					errortxt = "There is not enough memory\nto keep the undo buffer.\n\nThe undobuffer is lost.";
					break;
				case Error_StringNotFound:
					break;
				case Error_NoBookmarkInstalled:
					errortxt = "There is no bookmark installed!";
					break;
				case Error_BookmarkHasBeenLost:
					errortxt = "Your bookmark has unfortunately been lost.";
					break;
			}
			if(errortxt) {
				MUI_Request(app,wnd_account, 0L, NULL, "Continue", errortxt);
			}
			break;
	}
	return DoSuperMethodA(cl,obj,(Msg)msg);
}

/*ASM void desfunc_groupdata(REG(a2) APTR pool,REG(a1) GroupData * entry) {*/
void HOOK2( desfunc_groupdata, APTR, pool, a2, GroupData *, entry, a1 )
	/*if(entry)
		delete [] ((char *)entry);*/
	if(entry)
		delete entry;
}

/*ASM void desfunc_groupdatatree(REG(a0) Hook *hook,REG(a2) Object *obj,REG(a1) struct MUIP_NListtree_DestructMessage *msg) {*/
void HOOK3( desfunc_groupdatatree, Hook *, hook, a0, Object *, obj, a2, MUIP_NListtree_DestructMessage *, msg, a1 )
	if(msg->UserData) {
			delete msg->UserData;
			msg->UserData=NULL;
		}
}

/*ASM void desfunc_messagelistdata(REG(a2) APTR pool,REG(a1) MessageListData * entry) {*/
void HOOK2( desfunc_messagelistdata, APTR, pool, a2, MessageListData *, entry, a1 )
	if(entry)
		delete entry;
}

/*ASM void desfunc_search(REG(a2) APTR pool,REG(a1) MessageListData * entry) {*/
void HOOK2( desfunc_search, APTR, pool, a2, MessageListData *, entry, a1 )
	if(entry)
		delete entry;
}

void HOOK2( desfunc_joinmsgs, APTR, pool, a2, MessageListData *, entry, a1 )
	if(entry)
		delete entry;
}

/*ASM void desfunc_stats(REG(a2) APTR pool,REG(a1) StatsList * entry) {*/
void HOOK2( desfunc_stats, APTR, pool, a2, StatsList *, entry, a1 )
	if(entry)
		delete entry;
}

/*ASM void desfunc_users(REG(a2) APTR pool,REG(a1) User * entry) {*/
void HOOK2( desfunc_users, APTR, pool, a2, User *, entry, a1 )
	if(entry)
		delete entry;
}

/*ASM void desfunc_groupman(REG(a2) APTR pool,REG(a1) char * entry) {*/
void HOOK2( desfunc_groupman, APTR, pool, a2, char *, entry, a1 )
	if(entry)
		delete entry;
}

/*ASM void desfunc_servers(REG(a2) APTR pool,REG(a1) Server * entry) {*/
void HOOK2( desfunc_servers, APTR, pool, a2, Server *, entry, a1 )
	if(entry)
		delete entry;
}

/*ASM void desfunc_killfile(REG(a2) APTR pool,REG(a1) KillFile * entry) {*/
void HOOK2( desfunc_killfile, APTR, pool, a2, KillFile *, entry, a1 )
	if(entry)
		delete entry;
}

/*ASM void desfunc_mime(REG(a2) APTR pool,REG(a1) MIMEType * entry) {*/
void HOOK2( desfunc_mime, APTR, pool, a2, MIMEType *, entry, a1 )
	if(entry)
		delete entry;
}

/*ASM void desfunc_mimeprefs(REG(a2) APTR pool,REG(a1) MIMEPrefs * entry) {*/
void HOOK2( desfunc_mimeprefs, APTR, pool, a2, MIMEPrefs *, entry, a1 )
	if(entry)
		delete entry;
}

LONG HOOK2( dispfunc_simpleglist, char **, array, a2, GroupData *, data, a1 )
	if(data) {
		*array = (*data->desc!=0) ? data->desc : data->name;
	}
	else {
		*array = "\33bGroup";
	}
	return(0);
}

/*ASM LONG dispfunc_groupdata(REG(a2) char **array,REG(a1) GroupData * data) {*/
LONG HOOK2( dispfunc_groupdata, char **, array, a2, GroupData *, data, a1 )
	static char buf0[512];
	static char buf1[16];
	if(data) {
		char *name = (*data->desc!=0) ? data->desc : data->name;
		if(data->num_unread > 0) {
			sprintf(buf0,"\33b%s",name);
			*array++ = buf0;
		}
		else
			*array++ = name;

		sprintf(buf1,"%d",data->nummess);
		*array++ = buf1;

		if(data->s)
			*array++ = "S";
		else
			*array++ = "";
		if(data->ID<0)
			*array = "";
		else if(data->flags[5])
			*array = "Y";
		else
			*array = "N";
	}
	else {
		*array++ = "\33bGroup";
		*array++ = "\33bMsgs";
		*array++ = "\33bSub";
		*array = "\33bOnline";
	}
	return(0);
}

/*ASM LONG dispfunc_groupdatatree(REG(a0) struct Hook *hook,REG(a2) Object *obj,REG(a1) struct MUIP_NListtree_DisplayMessage *msg) {*/
LONG HOOK3( dispfunc_groupdatatree, Hook *, hook, a0, Object *, obj, a2, MUIP_NListtree_DisplayMessage *, msg, a1 )
	static char buf1[16];
	char **array = msg->Array;
	if(msg->TreeNode) {
		GroupData * data = (GroupData *)msg->TreeNode->tn_User;
		if(data) {
			sprintf(buf1,"%d",data->nummess);
			if(*data->desc!=0)
				*array++ = data->desc;
			else
				*array++ = data->name;
			*array++ = buf1;
			if(data->s)
				*array++ = "S";
			else
				*array++ = "";
			if(data->ID<0)
				*array = "";
			else if(data->flags[5])
				*array = "Y";
			else
				*array = "N";
		}
		else {
			if(msg->TreeNode->tn_Name)
				*array++ = msg->TreeNode->tn_Name;
			else
				*array++ = "";

			*array++ = "";
			*array = "";
		}
	}
	else {
		*array++ = "\33bGroup";
		*array++ = "\33bMessages";
		*array++ = "\33bSub";
		*array = "\33bOnline";
	}
	return(0);
}

/*ASM LONG confunc_groupdatatree(REG(a0) Hook *hook,REG(a2) Object *obj,REG(a1) struct MUIP_NListtree_ConstructMessage *msg) {*/
LONG HOOK3( confunc_groupdatatree, Hook *, hook, a0, Object *, obj, a2, MUIP_NListtree_ConstructMessage *, msg, a1 )
	GroupData *gdata = (GroupData *)msg->UserData;
	return ((LONG)gdata);
}


/*ASM LONG dispfunc_messagelistdata(REG(a2) char **array,REG(a1) MessageListData * data) {*/
LONG HOOK2( dispfunc_messagelistdata, char **, array, a2, MessageListData *, data, a1 )
	static int gID;
	static char buf0[16];
	static char buf1[512];
	static char buf2[16];
	static char buf3[16];
	static char buf4[64];
	//static char buf5[MAXLINE];
	if(data) {
		//printf("%s\n",data->subject);
		if((account.listflags & Account::LISTFLAGS)!=0) {
			char *buf0_ptr = buf0;
			if(data->flags[0]==TRUE)
				*buf0_ptr++ = 'H';
			else if(data->flags[10]==TRUE)
				*buf0_ptr++ = 'R';
			else if(data->flags[1]==TRUE)
				*buf0_ptr++ = 'U';
			if(data->flags[12]==TRUE)
				*buf0_ptr++ = '*';
			*buf0_ptr = '\0';
			*array++ = buf0;
		}

		if((account.listflags & Account::LISTSUBJECT)!=0) {
			if(!data->flags[13])
				*array++ = data->subject;
			else {
				sprintf(buf1,"\0338%.63s",data->subject);
				*array++ = buf1;
			}
		}

		if((account.listflags & Account::LISTDATE)!=0) {
			//if(*data->datec == '\0')
			//	sprintf(data->datec,"%s %s",data->c_date,data->c_time);
			//*array++ = data->datec;
			sprintf(buf4,"%s %s",data->c_date,data->c_time);
			*array++ = buf4;
		}

		if((account.listflags & Account::LISTFROMGROUP)!=0) {
			if(gID<0) {
				/*NewMessage newmess;
				get_refs(&newmess,gID,data->ID,GETREFS_NONE);
				*array++ = newmess.newsgroups;*/
				/*get_newsgroups(buf5,gID,data->ID);
				*array++ = buf5;*/
				*array++ = data->newsgroups;
			}
			else
				*array++ = data->from;
		}

		if((account.listflags & Account::LISTSIZE)!=0) {
			sprintf(buf2,"%d",data->size);
			*array++ = buf2;
		}

		if((account.listflags & Account::LISTLINES)!=0) {
			sprintf(buf3,"%d",data->flags[8]);
			*array++ = buf3;
		}
		
		array--;
	}
	else {
		GroupData * gdata=NULL;
		getGdataDisplayed(&gdata);
		if(gdata)
			gID=gdata->ID;
		else
			gID=0;
		if((account.listflags & Account::LISTFLAGS)!=0)
			*array++ = " ";
		if((account.listflags & Account::LISTSUBJECT)!=0)
			*array++ = "\33bSubject";
		if((account.listflags & Account::LISTDATE)!=0)
			*array++ = "\33bDate";
		if((account.listflags & Account::LISTFROMGROUP)!=0) {
			if(gID<0)
				*array++ = "\33bNewsgroups";
			else
				*array++ = "\33bFrom";
		}
		if((account.listflags & Account::LISTSIZE)!=0)
			*array++ = "\33bSize";
		if((account.listflags & Account::LISTLINES)!=0)
			*array++ = "\33bLines";
		
		array--;
	}
	return(0);
}

/*ASM LONG dispfunc_messagelistdatatree(REG(a0) struct Hook *hook,REG(a2) Object *obj,REG(a1) struct MUIP_NListtree_DisplayMessage *msg) {*/
LONG HOOK3( dispfunc_messagelistdatatree, Hook *, hook, a0, Object *, obj, a2, MUIP_NListtree_DisplayMessage *, msg, a1 )
	static int gID;
	static char buf0[16];
	static char buf1[512];
	static char buf2[16];
	static char buf3[16];
	static char buf4[64];
	char **array = msg->Array;
	if(msg->TreeNode) {
		MessageListData * data = (MessageListData *)msg->TreeNode->tn_User;
		if(data) {
			if((account.listflags & Account::LISTFLAGS)!=0) {
				char *buf0_ptr = buf0;
				if(data->flags[0]==TRUE)
					*buf0_ptr++ = 'H';
				else if(data->flags[10]==TRUE)
					*buf0_ptr++ = 'R';
				else if(data->flags[1]==TRUE)
					*buf0_ptr++ = 'U';
				if(data->flags[12]==TRUE)
					*buf0_ptr++ = '*';
				*buf0_ptr = '\0';
				*array++ = buf0;
			}

			if((account.listflags & Account::LISTSUBJECT)!=0) {
				if(!data->flags[13])
					*array++ = data->subject;
				else {
					sprintf(buf1,"\0338%.63s",data->subject);
					*array++ = buf1;
				}
			}

			if((account.listflags & Account::LISTDATE)!=0) {
				//if(*data->datec == '\0')
				//	sprintf(data->datec,"%s %s",data->c_date,data->c_time);
				//*array++ = data->datec;
				sprintf(buf4,"%s %s",data->c_date,data->c_time);
				*array++ = buf4;
			}

			if((account.listflags & Account::LISTFROMGROUP)!=0) {
				if(gID<0)
					*array++ = data->newsgroups;
				else
					*array++ = data->from;
			}

			if((account.listflags & Account::LISTSIZE)!=0) {
				sprintf(buf2,"%d",data->size);
				*array++ = buf2;
			}

			if((account.listflags & Account::LISTLINES)!=0) {
				sprintf(buf3,"%d",data->flags[8]);
				*array++ = buf3;
			}

			array--;
		}
		else {
			*array++ = msg->TreeNode->tn_Name;
			*array++ = "";
			*array = "";
		}
	}
	else {
		GroupData * gdata=NULL;
		getGdataDisplayed(&gdata);
		if(gdata)
			gID=gdata->ID;
		else
			gID=0;

		if((account.listflags & Account::LISTFLAGS)!=0)
			*array++ = " ";
		if((account.listflags & Account::LISTSUBJECT)!=0)
			*array++ = "\33bSubject";
		if((account.listflags & Account::LISTDATE)!=0)
			*array++ = "\33bDate";
		if((account.listflags & Account::LISTFROMGROUP)!=0) {
			if(gID<0)
				*array++ = "\33bNewsgroups";
			else
				*array++ = "\33bFrom";
		}
		if((account.listflags & Account::LISTSIZE)!=0)
			*array++ = "\33bSize";
		if((account.listflags & Account::LISTLINES)!=0)
			*array++ = "\33bLines";
		
		array--;

		/**array++ = " ";
		*array++ = "\33bSubject";
		*array++ = "\33bDate";
		if(gID<0)
			*array++ = "\33bNewsgroups";
		else
			*array++ = "\33bFrom";
		*array++ = "\33bSize";
		*array = "\33bLines";*/
	}
	return(0);
}

/*ASM LONG dispfunc_search(REG(a2) char **array,REG(a1) MessageListData * data) {*/
LONG HOOK2( dispfunc_search, char **, array, a2, MessageListData *, data, a1 )
	static char buf0[16];
	static char buf1[512];
	static char buf2[16];
	static char buf3[16];
	static char buf4[64];
	if(data) {
		if((account.listflags & Account::LISTFLAGS)!=0) {
			char *buf0_ptr = buf0;
			if(data->flags[0]==TRUE)
				*buf0_ptr++ = 'H';
			else if(data->flags[10]==TRUE)
				*buf0_ptr++ = 'R';
			else if(data->flags[1]==TRUE)
				*buf0_ptr++ = 'U';
			if(data->flags[12]==TRUE)
				*buf0_ptr++ = '*';
			*buf0_ptr = '\0';
			*array++ = buf0;
		}

		if((account.listflags & Account::LISTSUBJECT)!=0) {
			if(!data->flags[13])
				*array++ = data->subject;
			else {
				sprintf(buf1,"\0338%.63s",data->subject);
				*array++ = buf1;
			}
		}

		if((account.listflags & Account::LISTDATE)!=0) {
			//if(*data->datec == '\0')
			//	sprintf(data->datec,"%s %s",data->c_date,data->c_time);
			//*array++ = data->datec;
			sprintf(buf4,"%s %s",data->c_date,data->c_time);
			*array++ = buf4;
		}

		if((account.listflags & Account::LISTFROMGROUP)!=0)
			*array++ = data->from;

		if((account.listflags & Account::LISTSIZE)!=0) {
			sprintf(buf2,"%d",data->size);
			*array++ = buf2;
		}

		if((account.listflags & Account::LISTLINES)!=0) {
			sprintf(buf3,"%d",data->flags[8]);
			*array++ = buf3;
		}
		
		array--;
		
	}
	else {
		if((account.listflags & Account::LISTFLAGS)!=0)
			*array++ = " ";
		if((account.listflags & Account::LISTSUBJECT)!=0)
			*array++ = "\33bSubject";
		if((account.listflags & Account::LISTDATE)!=0)
			*array++ = "\33bDate";
		if((account.listflags & Account::LISTFROMGROUP)!=0)
			*array++ = "\33bFrom";
		if((account.listflags & Account::LISTSIZE)!=0)
			*array++ = "\33bSize";
		if((account.listflags & Account::LISTLINES)!=0)
			*array++ = "\33bLines";
		
		array--;
		
	}
	return(0);
}

LONG HOOK2( dispfunc_joinmsgs, char **, array, a2, MessageListData *, data, a1 )
	static char buf0[16];
	static char buf1[512];
	static char buf2[16];
	static char buf3[16];
	static char buf4[64];
	if(data) {
		if((account.listflags & Account::LISTFLAGS)!=0) {
			char *buf0_ptr = buf0;
			if(data->flags[0]==TRUE)
				*buf0_ptr++ = 'H';
			else if(data->flags[10]==TRUE)
				*buf0_ptr++ = 'R';
			else if(data->flags[1]==TRUE)
				*buf0_ptr++ = 'U';
			if(data->flags[12]==TRUE)
				*buf0_ptr++ = '*';
			*buf0_ptr = '\0';
			*array++ = buf0;
		}

		if((account.listflags & Account::LISTSUBJECT)!=0) {
			if(!data->flags[13])
				*array++ = data->subject;
			else {
				sprintf(buf1,"\0338%.63s",data->subject);
				*array++ = buf1;
			}
		}

		if((account.listflags & Account::LISTDATE)!=0) {
			sprintf(buf4,"%s %s",data->c_date,data->c_time);
			*array++ = buf4;
		}

		if((account.listflags & Account::LISTFROMGROUP)!=0)
			*array++ = data->from;

		if((account.listflags & Account::LISTSIZE)!=0) {
			sprintf(buf2,"%d",data->size);
			*array++ = buf2;
		}

		if((account.listflags & Account::LISTLINES)!=0) {
			sprintf(buf3,"%d",data->flags[8]);
			*array++ = buf3;
		}
		
		array--;
		
	}
	else {
		if((account.listflags & Account::LISTFLAGS)!=0)
			*array++ = " ";
		if((account.listflags & Account::LISTSUBJECT)!=0)
			*array++ = "\33bSubject";
		if((account.listflags & Account::LISTDATE)!=0)
			*array++ = "\33bDate";
		if((account.listflags & Account::LISTFROMGROUP)!=0)
			*array++ = "\33bFrom";
		if((account.listflags & Account::LISTSIZE)!=0)
			*array++ = "\33bSize";
		if((account.listflags & Account::LISTLINES)!=0)
			*array++ = "\33bLines";
		
		array--;
		
	}
	return(0);
}

/*ASM LONG dispfunc_stats(REG(a2) char **array,REG(a1) struct StatsList * data) {*/
LONG HOOK2( dispfunc_stats, char **, array, a2, StatsList *, data, a1 )
	static char buf1[16];
	if(data) {
		sprintf(buf1,"%d",data->freq);
		*array++ = data->value;
		*array = buf1;
	}
	else {
		*array++ = "\33bValue";
		*array = "\33bFrequency";
	}
	return(0);
}

/*ASM LONG dispfunc_users(REG(a2) char **array,REG(a1) struct User * data) {*/
LONG HOOK2( dispfunc_users, char **, array, a2, User *, data, a1 )
	if(data) {
		*array++ = data->getName();
		*array++ = data->dataLocation;
		if(data->requiresPassword())
			*array++ = "Y";
		else
			*array++ = "N";
		if(data->isSupervisor())
			*array = "Y";
		else
			*array = "N";
	}
	else {
		*array++ = "\33bName";
		*array++ = "\33bNews Directory";
		*array++ = "\33bPassword Protected?";
		*array = "\33bSupervisor?";
	}
	return(0);
}

/*ASM LONG dispfunc_mime(REG(a2) char **array,REG(a1) struct MIMEType * data) {*/
LONG HOOK2( dispfunc_mime, char **, array, a2, MIMEType *, data, a1 )
	static char buf1[16];
	if(data) {
		sprintf(buf1,"%d",data->size);
		*array++ = data->file;
		*array++ = data->type;
		*array = buf1;
	}
	else {
		*array++ = "\33bFilename";
		*array++ = "\33bMIME Type";
		*array = "\33bSize";
	}
	return(0);
}

/*ASM LONG dispfunc_mimeprefs(REG(a2) char **array,REG(a1) struct MIMEPrefs * data) {*/
LONG HOOK2( dispfunc_mimeprefs, char **, array, a2, MIMEPrefs *, data, a1 )
	if(data) {
		*array++ = data->type;
		*array = data->viewer;
	}
	else {
		*array++ = "\33bMIME Type";
		*array = "\33bViewer";
	}
	return(0);
}

/*ASM LONG dispfunc_killfile(REG(a2) char **array,REG(a1) KillFile * data) {*/
LONG HOOK2( dispfunc_killfile, char **, array, a2, KillFile *, data, a1 )
	static char buf1[128],buf2[128],buf3[64];
	static DateTime dt;
	if(data) {
		dt.dat_Stamp=data->ds;
		dt.dat_Format=FORMAT_DOS;
		dt.dat_Flags=NULL;
		dt.dat_StrDay=NULL;
		dt.dat_StrDate=(unsigned char *)buf1;
		dt.dat_StrTime=NULL;
		DateToStr(&dt);
		dt.dat_Stamp=data->lastused;
		dt.dat_StrDate=(unsigned char *)buf2;
		DateToStr(&dt);
		if(data->expiretype==0)
			strcpy(buf3,"Indefinately");
		else if(data->expiretype==1)
			sprintf(buf3,"%d days since Creation",data->expire);
		else if(data->expiretype==2)
			sprintf(buf3,"%d days since Last Used",data->expire);
		
		*array++ = data->header;
		*array++ = data->text;
		*array++ = data->ngroups;
		/*if(data->type == 0)
			*array++ = "Kill";
		else if(data->type == 1)
			*array++ = "Keep";
		else if(data->type == 2)
			*array++ = "Important";
		else
			*array++ = "Unknown???";*/

		if(data->match == 0)
			*array++ = "Contains";
		else if(data->match == 1)
			*array++ = "Doesn't Contain";
		else
			*array++ = "Unknown???";

		if(data->action == 0)
			*array++ = "Kill";
		else if(data->action == 1)
			*array++ = "Mark As Important";
		else
			*array++ = "Unknown???";
		
		*array++ = data->carryon ? "N" : "Y";

		*array++ = buf1;
		*array++ = buf2;
		*array = buf3;
	}
	else {
		*array++ = "\33bHeader";
		*array++ = "\33bText";
		*array++ = "\33bGroups";
		*array++ = "\33bMatch";
		*array++ = "\33bAction";
		*array++ = "\33bSkip Rest?";
		*array++ = "\33bCreation";
		*array++ = "\33bLast Used";
		*array = "\33bTime Limit";
	}
	return(0);
}

/*ASM LONG dispfunc_servers(REG(a2) char **array,REG(a1) Server * data) {*/
LONG HOOK2( dispfunc_servers, char **, array, a2, Server *, data, a1 )
	static char buf1[16],buf2[4],buf3[4],buf4[4];
	if(data) {
		sprintf(buf1,"%d",data->port);
		
		if(data->nntp_auth)
			strcpy(buf2,"Y");
		else
			strcpy(buf2,"N");
		
		if(data->def)
			strcpy(buf3,"Y");
		else
			strcpy(buf3,"N");
		
		if(data->post)
			strcpy(buf4,"Y");
		else
			strcpy(buf4,"N");

		*array++ = data->nntp;
		*array++ = buf1;
		*array++ = data->user;
		//*array++ = data->password;
		*array++ = buf2;
		*array++ = buf3;
		*array = buf4;
	}
	else {
		*array++ = "\33bServer";
		*array++ = "\33bPort";
		*array++ = "\33bUsername";
		//*array++ = "\33bPassword";
		*array++ = "\33bAuthentication";
		*array++ = "\33bDefault";
		*array = "\33bPosting";
	}
	return(0);
}

/*ASM LONG cmpfunc_groupdata(REG(a1) GroupData * gdata1,REG(a2) GroupData *gdata2) {*/
LONG HOOK2( cmpfunc_groupdata, GroupData *, gdata1, a1, GroupData*, gdata2, a2 )
	STRPTR n1,n2;
	if(gdata1->ID<0 && gdata2->ID>=0)
		return -1;
	if(gdata2->ID<0 && gdata1->ID>=0)
		return 1;

	if(gdata1->ID==-3) {
		if(gdata2->ID<0)
			return 1;
		else
			return -1;
	}
	if(gdata2->ID==-3) {
		if(gdata1->ID<0)
			return -1;
		else
			return 1;
	}

	if(*gdata1->desc!=0)
		n1=gdata1->desc;
	else
		n1=gdata1->name;
	if(*gdata2->desc!=0)
		n2=gdata2->desc;
	else
		n2=gdata2->name;
	return(stricmp(n1,n2));
}

LONG compare_messagelistdata(MessageListData *mdata1,MessageListData *mdata2,int sorttype,int sorttypedir) {
	// sorttype: 0=subject, 1=date, 2=from, -1=newsgroups, 3=size, 4=lines
	static char buffer1[256]="";
	static char buffer2[256]="";
	char *b1 = NULL,*b2 = NULL;
	LONG result = 0;
	//printf("%d %d\n",mdata1->ID,mdata2->ID);
	switch(sorttype) {
	case 0:
		//subject
		b1 = mdata1->subject;
		b2 = mdata2->subject;
		while(*b1!=0 && (strincmp_q(b1,"RE: ",4)==0 || strincmp_q(b1,"SV: ",4)==0))
			b1 += 4;
		while(*b2!=0 && (strincmp_q(b2,"RE: ",4)==0 || strincmp_q(b2,"SV: ",4)==0))
			b2 += 4;
		result=stricmp(b1,b2);
		break;
	case 1:
		//date
		result=-CompareDates(&mdata1->ds,&mdata2->ds);
		break;
	case 2:
		//from
		get_email(buffer1,mdata1->from,GETEMAIL_NAMEEMAIL);
		get_email(buffer2,mdata2->from,GETEMAIL_NAMEEMAIL);
		if(*buffer1=='\"')
			b1=buffer1+1;
		else
			b1=buffer1;
		if(*buffer2=='\"')
			b2=buffer2+1;
		else
			b2=buffer2;
		result=stricmp(b1,b2);
		break;
	case -1:
		//newsgroups
		result=stricmp(mdata1->newsgroups,mdata2->newsgroups);
		break;
	case 3:
		//size
		if(mdata1->size < mdata2->size)
			result=-1;
		else if(mdata1->size > mdata2->size)
			result=1;
		else
			result=0;
		break;
	case 4:
		//lines
		if(mdata1->flags[8] < mdata2->flags[8])
			result=-1;
		else if(mdata1->flags[8] > mdata2->flags[8])
			result=1;
		else
			result=0;
		break;
	}
	if(result!=0 || sorttype==1)
		return result * sorttypedir;
	//date
	result=-CompareDates(&mdata1->ds,&mdata2->ds);
	return result * sorttypedir;
}

/*ASM LONG cmpfunc_messagelistdata(REG(a1) MessageListData * mdata1,REG(a2) MessageListData *mdata2) {*/
LONG HOOK2( cmpfunc_messagelistdata, MessageListData *, mdata1, a1, MessageListData *, mdata2, a2 )
	return compare_messagelistdata(mdata1,mdata2,account.sorttype,account.sorttypedir);
}

/*ASM LONG cmpfunc_messagelistdatatree(REG(a0) struct Hook *hook,REG(a2) Object *obj,REG(a1) struct MUIP_NListtree_CompareMessage *msg) {*/
LONG HOOK3( cmpfunc_messagelistdatatree, Hook *, hook, a0, Object *, obj, a2, MUIP_NListtree_CompareMessage *, msg, a1 )
	//return cmpfunc_messagelistdata((MessageListData *)msg->TreeNode1->tn_User,(MessageListData *)msg->TreeNode2->tn_User);
	return compare_messagelistdata((MessageListData *)msg->TreeNode1->tn_User,(MessageListData *)msg->TreeNode2->tn_User,account.sorttype,account.sorttypedir);
}

LONG HOOK2( cmpfunc_search, MessageListData *, mdata1, a1, MessageListData *, mdata2, a2 )
	return compare_messagelistdata(mdata1,mdata2,sorttype_search,sorttypedir_search);
}

LONG HOOK2( cmpfunc_joinmsgs, MessageListData *, mdata1, a1, MessageListData *, mdata2, a2 )
	return compare_messagelistdata(mdata1,mdata2,sorttype_search,sorttypedir_search);
}

/*ASM LONG cmpfunc_stats(REG(a1) struct StatsList * data1,REG(a2) struct StatsList *data2) {*/
LONG HOOK2( cmpfunc_stats, StatsList *, data1, a1, StatsList *, data2, a2 )
	// sorttype_stats: 0=value, 1=frequency
	static char buffer1[256]="";
	static char buffer2[256]="";
	char *b1 = NULL,*b2 = NULL;
	LONG result = 0;
	if(sorttype_stats==0) {
		//value
		if(stats_what==0) {
			// from
			get_email(buffer1,data1->value,GETEMAIL_NAMEEMAIL);
			get_email(buffer2,data2->value,GETEMAIL_NAMEEMAIL);
			if(*buffer1=='\"')
				b1=buffer1+1;
			else
				b1=buffer1;
			if(*buffer2=='\"')
				b2=buffer2+1;
			else
				b2=buffer2;
			result=stricmp(b1,b2);
		}
		else if(stats_what==1) {
			// subject
			/*b1 = data1->value;
			b2 = data2->value;
			while(*b1!=0 && (strincmp_q(b1,"RE: ",4)==0 || strincmp_q(b1,"SV: ",4)==0))
				b1 += 4;
			while(*b2!=0 && (strincmp_q(b2,"RE: ",4)==0 || strincmp_q(b2,"SV: ",4)==0))
				b2 += 4;
			result=stricmp(b1,b2);*/
			result=stricmp(data1->value,data2->value);
		}
		else if(stats_what==2) {
			// xnewsreader
			result=stricmp(data1->value,data2->value);
		}
	}
	else if(sorttype_stats==1) {
		if(data1->freq > data2->freq)
			result = 1;
		else if (data1->freq < data2->freq)
			result = -1;
	}
	return result * sorttypedir_stats;
}

/*ASM LONG cmpfunc_users(REG(a1) struct User * data1,REG(a2) struct User *data2) {*/
LONG HOOK2( cmpfunc_users, User *, data1, a1, User *, data2, a2 )
	return stricmp(data1->getName(),data2->getName());
}

LONG HOOK3( mdata_changed, Hook *, hook, a0, Object *, object, a2, ULONG *, p, a1 )
	setEnabled();
	return 0;
}

/*ASM LONG do_arexx(REG(a1) struct RexxMsg * msg,REG(a2) Object * app) {*/
LONG HOOK2( do_arexx, RexxMsg *, msg, a1, Object *, app, a2 )
	GroupData * gdata = NULL;
	MessageListData * mdata = NULL;
	char *rexx=NULL;
	char word1[1024] = "";
	char word2[1024] = "";
	char word3[1024] = "";
	char buffer[1024]="";
	LONG rc=0;
	int result=0;
	int entries=0;
	for(int k=0;k<16;k++) {
		rexx = msg->rm_Args[k];
		if(rexx!=NULL) {
			word(word1,rexx,1);
			word(word2,rexx,2);
			word(word3,rexx,3);
			if(stricmp(word1,"BUSY")==0)
				set(app,MUIA_Application_Sleep,TRUE);
			else if(stricmp(word1,"FETCHNEWS")==0) {
				if(delete_dis)
					rc=1;
				else
					getnews(-1);
			}
			else if(stricmp(word1,"FETCHNEWSBYID")==0) {
				if(*word2 != NULL) {
					if(delete_dis)
						rc=1;
					else {
						int id=0;
						id = atoi(word2);
						int pos=get_gdataPos(id);
						if(pos==-1)
							rc=1;
						else {
							getGdata(pos,&gdata);
							if(gdata) {
								if(gdata->ID>=0)
									getnews(pos);
								else
									rc=1;
							}
							else
								rc=1;
						}
					}
				}
				else
					rc=1;
			}
			else if(stricmp(word1,"FETCHNEWSBYNAME")==0) {
				if(*word2 != NULL) {
					if(delete_dis)
						rc=1;
					else {
						int pos=get_gdataPos(word2);
						if(pos==-1)
							rc=1;
						else {
							getGdata(pos,&gdata);
							if(gdata) {
								if(gdata->ID>=0)
									getnews(pos);
								else
									rc=1;
							}
							else
								rc=1;
						}
					}
				}
				else
					rc=1;
			}
			else if(stricmp(word1,"FETCHNEWSBYPOS")==0) {
				if(*word2 != NULL) {
					if(delete_dis)
						rc=1;
					else {
						int pos=0;
						pos = atoi(word2);
						getGdata(pos,&gdata);
						if(gdata) {
							if(gdata->ID>=0)
								getnews(pos);
							else
								rc=1;
						}
						else
							rc=1;
					}
				}
				else
					rc=1;
			}
			else if(stricmp(word1,"FOLDERINFO")==0) {
				getGdataDisplayed(&gdata);
				sprintf(buffer,"%d %s %s %d %d %d %d",gdata->ID,gdata->name,gdata->desc,gdata->nummess,gdata->nextmID,gdata->s,gdata->max_dl);
				set(app,MUIA_Application_RexxString,buffer);
			}
			else if(stricmp(word1,"HIDE")==0)
				set(app,MUIA_Application_Iconified,TRUE);
			else if(stricmp(word1,"IMPORTFOLDER")==0) {
				if(*word2 != NULL) {
					StatusWindow *statusWindow = new StatusWindow(app,"Importing Folder..");
					import_folder(word2,statusWindow);
					delete statusWindow;
				}
			}
			else if(stricmp(word1,"IMPORTMESSAGE")==0) {
				if(*word2 != NULL)
					import_file(word2);
			}
			else if(stricmp(word1,"ISONLINE")==0) {
				if(delete_dis)
					rc=1;
				else
					rc=0;
			}
			else if(stricmp(word1,"MESSAGEFUANDR")==0)
				DoMethod(app,MUIM_Application_ReturnID,MEN_BOTH);
			else if(stricmp(word1,"MESSAGECOPY")==0) {
				if(*word2 != NULL)
					move_multi(1,word2);
			}
			else if(stricmp(word1,"MESSAGEDELETE")==0) {
				BOOL confirm=TRUE;
				if(*word2 != NULL) {
					if(stricmp(word2,"FORCE")==0)
						confirm=FALSE;
				}
				delete_multi(confirm);
			}
			else if(stricmp(word1,"MESSAGEEDIT")==0)
				DoMethod(app,MUIM_Application_ReturnID,MEN_EDIT);
			else if(stricmp(word1,"MESSAGEEXPORT")==0)
				DoMethod(app,MUIM_Application_ReturnID,MEN_EXP);
			else if(stricmp(word1,"MESSAGEFOLLOWUP")==0)
				DoMethod(app,MUIM_Application_ReturnID,MEN_FOLLOWUP);
			else if(stricmp(word1,"MESSAGEGETHEADER")==0) {
				if(*word2 != NULL) {
					getGdataDisplayed(&gdata);
					getMdataActive(&mdata);
					NewMessage tempNM;
					strncpy(tempNM.getThisHeader,word2,NEWMESS_shortshort);
					tempNM.getThisHeader[NEWMESS_shortshort] = '\0';
					get_refs(&tempNM,gdata,mdata,GETREFS_NONE);
					strcpy(buffer,tempNM.dummyHeader);
					set(app,MUIA_Application_RexxString,buffer);
				}
				else
					rc=5;
			}
			else if(stricmp(word1,"MESSAGEGETPATH")==0) {
				getGdataDisplayed(&gdata);
				getMdataActive(&mdata);
				getFilePath(buffer,gdata->ID,mdata->ID);
				set(app,MUIA_Application_RexxString,buffer);
			}
			else if(stricmp(word1,"MESSAGEINFO")==0) {
				getGdataDisplayed(&gdata);
				getMdataActive(&mdata);
				//if(*mdata->datec == '\0')
				//	sprintf(mdata->datec,"%s %s",mdata->c_date,mdata->c_time);
				NewMessage newmess;
				get_refs(&newmess,gdata->ID,mdata->ID,GETREFS_NONE);
				//sprintf(buffer,"%d %s %s %s %s %s %s %s",mdata->ID,mdata->from,mdata->newsgroups,mdata->subject,mdata->c_date,mdata->c_time,mdata->messageID,mdata->type);
				sprintf(buffer,"%d %s %s %s %s %s %s %s",mdata->ID,newmess.from,newmess.newsgroups,newmess.subject,mdata->c_date,mdata->c_time,newmess.messageID,newmess.type);
				set(app,MUIA_Application_RexxString,buffer);
			}
			else if(stricmp(word1,"MESSAGEKILL")==0) {
				int type=0;
				if(*word2 != NULL) {
					type = atoi(word2); // must be 0,1,2
					if(type<0 || type>2)
						rc=5;
					else {
						if(*word3 != NULL)
						{
							if(stricmp(word3,"THISGROUP")==0)
								type += 4;
						}
					}
				}
				else
					type=-1;
				if(rc==0) {
					GroupData * gdata = NULL;
					MessageListData * mdata = NULL;
					getGdataDisplayed(&gdata);
					getMdataActivePos(&result);
					if(result!=MUIV_NList_Active_Off) {
						getMdataActive(&mdata);
						killmess(gdata,mdata,type);
					}
				}
			}
			else if(stricmp(word1,"MESSAGEMOVE")==0) {
				if(*word2 != NULL)
					move_multi(0,word2);
			}
			else if(stricmp(word1,"MESSAGEPOST")==0)
				DoMethod(app,MUIM_Application_ReturnID,MEN_POST);
			else if(stricmp(word1,"MESSAGEREPLY")==0)
				DoMethod(app,MUIM_Application_ReturnID,MEN_REPLY);
			else if(stricmp(word1,"MESSAGESUPERSEDE")==0)
				DoMethod(app,MUIM_Application_ReturnID,MEN_SUPER);
			else if(stricmp(word1,"NOBUSY")==0)
				set(app,MUIA_Application_Sleep,FALSE);
			else if(stricmp(word1,"QUIT")==0)
				DoMethod(app,MUIM_Application_ReturnID,MUIV_Application_ReturnID_Quit);
			else if(stricmp(word1,"SELECTMESSAGE")==0) {
				if(*word2 != NULL) {
					int v=0; // 1-=delselect, 1=select, 0=toggle
					v = atoi(word2);
					int which = MUIV_NList_Select_Active;
					if(*word3 != NULL) {
						if(stricmp(word3,"ALL")==0) {
							if(account.mdata_view==0)
								which=MUIV_NList_Select_All;
							else
								which=MUIV_NList_Select_All;
						}
					}
					if(account.mdata_view==0) {
						if(v==-1)
							DoMethod(NLIST_messagelistdata,MUIM_NList_Select,which,MUIV_NList_Select_Off,NULL);
						else if(v==0)
							DoMethod(NLIST_messagelistdata,MUIM_NList_Select,which,MUIV_NList_Select_Toggle,NULL);
						else if(v==1)
							DoMethod(NLIST_messagelistdata,MUIM_NList_Select,which,MUIV_NList_Select_On,NULL);
					}
					else {
						if(v==-1)
							DoMethod(LISTTREE_messagelistdata,MUIM_NList_Select,which,MUIV_NList_Select_Off,NULL);
						else if(v==0)
							DoMethod(LISTTREE_messagelistdata,MUIM_NList_Select,which,MUIV_NList_Select_Toggle,NULL);
						else if(v==1)
							DoMethod(LISTTREE_messagelistdata,MUIM_NList_Select,which,MUIV_NList_Select_On,NULL);
					}
				}
				else
					rc=5;
			}
			else if(stricmp(word1,"SENDNEWS")==0) {
				if(delete_dis)
					rc=1;
				else
					postnews(0);
			}
			else if(stricmp(word1,"SETFOLDER")==0) { // by pos
				if(*word2 != NULL) {
					int pos=0;
					pos = atoi(word2);
					getGdataEntries(&entries);
					if(pos>=0 && pos<entries)
						setGdataActive(pos);
					else
						rc=5;
				}
			}
			else if(stricmp(word1,"SETFOLDERBYID")==0) { // by ID
				if(*word2 != NULL) {
					int id=0;
					id = atoi(word2);
					set_and_read(id);
				}
			}
			else if(stricmp(word1,"SETFOLDERBYNAME")==0) { // by name
				if(*word2 != NULL)
					set_and_read(word2);
			}
			else if(stricmp(word1,"SETMESSAGE")==0) { // by pos
				if(*word2 != NULL) {
					int pos=0;
					sscanf(word2,"%d",&pos);
					get(NLIST_messagelistdata,MUIA_NList_Entries,&entries);
					if(pos>=0 && pos<entries)
						setMdataActive(pos);
					else
						rc=5;
				}
				else
					rc=5;
			}
			else if(stricmp(word1,"SHOW")==0)
				set(app,MUIA_Application_Iconified,FALSE);
		}
	}
	return rc;
}

VOID HOOK3( openfunc_messagelistdata, Hook *, hook, a0, Object*, obj, a2, struct MUIP_NListtree_OpenMessage *, openmsg, a1 )
	MUI_NListtree_TreeNode *treenode = openmsg->TreeNode;
	MUI_NListtree_TreeNode *child = (MUI_NListtree_TreeNode *)DoMethod(obj,MUIM_NListtree_GetEntry,treenode,MUIV_NListtree_GetEntry_Position_Head,0);

	//set(obj, MUIA_NListtree_OpenHook, NULL);
	//printf("!!!%d\n",hook);

	while(child != NULL) {
		//printf("child..\n");
		DoMethod(obj, MUIM_NListtree_Open, treenode, child, 0);
		//DoMethod(obj, MUIM_NListtree_Open, child, MUIV_NListtree_Open_TreeNode_All, 0);
		child = (MUI_NListtree_TreeNode *)DoMethod(obj,MUIM_NListtree_GetEntry,child,MUIV_NListtree_GetEntry_Position_Next,0);
	}

	//set(obj, MUIA_NListtree_OpenHook, hook);
	//printf("..\n");
}
const Hook OpenHook_messagelistdata={ {NULL,NULL},(HOOKFUNC)openfunc_messagelistdata,NULL,NULL};

/*VOID HOOK2( intuimsg_func, IntuiMessage *, imsg, a1, FileRequester *, req, a2 )
	if(imsg->Class == IDCMP_REFRESHWINDOW)
		DoMethod(app,MUIM_Application_CheckRefresh);
}*/

const Hook StrObjHook = { { NULL,NULL },(HOOKFUNC)StrObjFunc,NULL,NULL };
const Hook ObjStrAccHook = { { NULL,NULL },(HOOKFUNC)ObjStrAccFunc,NULL,NULL };
const Hook ObjStrAcc2Hook = { { NULL,NULL },(HOOKFUNC)ObjStrAcc2Func,NULL,NULL };
const Hook ObjStrAcc3Hook = { { NULL,NULL },(HOOKFUNC)ObjStrAcc3Func,NULL,NULL };
const Hook ObjStrNewuserHook = { { NULL,NULL },(HOOKFUNC)ObjStrNewuserFunc,NULL,NULL };
const Hook WindowHook = { { NULL,NULL },(HOOKFUNC)WindowFunc,NULL,NULL };
const Hook DestructHook_groupdata={ {NULL,NULL},(HOOKFUNC)desfunc_groupdata,NULL,NULL};
const Hook DestructHook_groupdatatree={ {NULL,NULL},(HOOKFUNC)desfunc_groupdatatree,NULL,NULL};
const Hook DestructHook_messagelistdata={ {NULL,NULL},(HOOKFUNC)desfunc_messagelistdata,NULL,NULL};
const Hook DestructHook_search={ {NULL,NULL},(HOOKFUNC)desfunc_search,NULL,NULL};
const Hook DestructHook_joinmsgs={ {NULL,NULL},(HOOKFUNC)desfunc_joinmsgs,NULL,NULL};
const Hook DestructHook_stats={ {NULL,NULL},(HOOKFUNC)desfunc_stats,NULL,NULL};
const Hook DestructHook_users={ {NULL,NULL},(HOOKFUNC)desfunc_users,NULL,NULL};
const Hook DestructHook_groupman={ {NULL,NULL},(HOOKFUNC)desfunc_groupman,NULL,NULL};
const Hook DestructHook_servers={ {NULL,NULL},(HOOKFUNC)desfunc_servers,NULL,NULL};
const Hook DestructHook_killfile={ {NULL,NULL},(HOOKFUNC)desfunc_killfile,NULL,NULL};
const Hook DestructHook_mime={ {NULL,NULL},(HOOKFUNC)desfunc_mime,NULL,NULL};
const Hook DestructHook_mimeprefs={ {NULL,NULL},(HOOKFUNC)desfunc_mimeprefs,NULL,NULL};
const Hook DisplayHook_simpleglist={ {NULL,NULL},(HOOKFUNC)dispfunc_simpleglist,NULL,NULL};
const Hook DisplayHook_groupdata={ {NULL,NULL},(HOOKFUNC)dispfunc_groupdata,NULL,NULL};
const Hook DisplayHook_groupdatatree={ {NULL,NULL},(HOOKFUNC)dispfunc_groupdatatree,NULL,NULL};
const Hook ConstructHook_groupdatatree={ {NULL,NULL},(HOOKFUNC)confunc_groupdatatree,NULL,NULL};
const Hook DisplayHook_messagelistdata={ {NULL,NULL},(HOOKFUNC)dispfunc_messagelistdata,NULL,NULL};
const Hook DisplayHook_messagelistdatatree={ {NULL,NULL},(HOOKFUNC)dispfunc_messagelistdatatree,NULL,NULL};
const Hook DisplayHook_search={ {NULL,NULL},(HOOKFUNC)dispfunc_search,NULL,NULL};
const Hook DisplayHook_joinmsgs={ {NULL,NULL},(HOOKFUNC)dispfunc_joinmsgs,NULL,NULL};
const Hook DisplayHook_stats={ {NULL,NULL},(HOOKFUNC)dispfunc_stats,NULL,NULL};
const Hook DisplayHook_users={ {NULL,NULL},(HOOKFUNC)dispfunc_users,NULL,NULL};
const Hook DisplayHook_mime={ {NULL,NULL},(HOOKFUNC)dispfunc_mime,NULL,NULL};
const Hook DisplayHook_mimeprefs={ {NULL,NULL},(HOOKFUNC)dispfunc_mimeprefs,NULL,NULL};
const Hook DisplayHook_servers={ {NULL,NULL},(HOOKFUNC)dispfunc_servers,NULL,NULL};
const Hook DisplayHook_killfile={ {NULL,NULL},(HOOKFUNC)dispfunc_killfile,NULL,NULL};
const Hook CompareHook_groupdata={ {NULL,NULL},(HOOKFUNC)cmpfunc_groupdata,NULL,NULL};
const Hook CompareHook_messagelistdata={ {NULL,NULL},(HOOKFUNC)cmpfunc_messagelistdata,NULL,NULL};
const Hook CompareHook_messagelistdatatree={ {NULL,NULL},(HOOKFUNC)cmpfunc_messagelistdatatree,NULL,NULL};
const Hook CompareHook_search={ {NULL,NULL},(HOOKFUNC)cmpfunc_search,NULL,NULL};
const Hook CompareHook_joinmsgs={ {NULL,NULL},(HOOKFUNC)cmpfunc_joinmsgs,NULL,NULL};
const Hook CompareHook_stats={ {NULL,NULL},(HOOKFUNC)cmpfunc_stats,NULL,NULL};
const Hook CompareHook_users={ {NULL,NULL},(HOOKFUNC)cmpfunc_users,NULL,NULL};
const Hook MdataChangedHook={ {NULL,NULL},(HOOKFUNC)mdata_changed,NULL,NULL};
const Hook ARexxHook={ {NULL,NULL},(HOOKFUNC)do_arexx,NULL,NULL};

/*const Hook IntuiMsgHook = { { NULL,NULL },(HOOKFUNC)intuimsg_func,NULL,NULL };*/

long askStack() {
	Process *process = (Process *)FindTask(0L);
	long stack = (char *)process->pr_Task.tc_SPUpper - (char *)process->pr_Task.tc_SPLower;
	//printf("%d\n",stack);
	return stack;
}

int realmain_2() {
	//nlisttree = FALSE;

	if(ASLlib.isopen()==FALSE) {
		printf("Unable to open ASL library!\n");
		return 0;
	}
	if(Localelib.isopen()==FALSE) {
		printf("Unable to open Locale library!\n");
		return 0;
	}

	/*const int MINSTACK = 100000;
	int stack = askStack();
	printf("%d\n",stack);
	if( stack < MINSTACK ) {
		printf("Need more stack size - currently %d; must be at least %d!\n",stack,MINSTACK);
		return 0;
	}*/

	initNetstuff();
	
	init();
	
	static const char TEXT_About[] = "Please see the AmigaGuide documentation for more information.";
	sprintf(newscoaster_name,"NewsCoaster v%s",version);
	sprintf(base_scrtitle,"%s ©1999-2002 Mark Harman",newscoaster_name);
	strcpy(scrtitle,base_scrtitle);

	if(!(editor_mcc = MUI_CreateCustomClass(NULL, "TextEditor.mcc", NULL, 0, (void *)TextEditor_Dispatcher)))
	{
		fail(app,"Failed to create Text Editor Custom Class.");
		return 0;
	}
	char abouttext[256]="";
	sprintf(abouttext,"\33c\33bNewsCoaster\33n\n(v%s)\n©1999-2002 Mark Harman",version);

	CYA_ngadv_server = new char *[2];
	CYA_ngadv_server[0] = new char[64];
	CYA_ngadv_server[1] = NULL;
	strcpy(CYA_ngadv_server[0],"");
	server_list = new int[1];
	server_list[0] = 0;

	SLD_acc_SIG = ScrollbarObject, End;

	app = ApplicationObject,
		MUIA_Application_Title      , "NewsCoaster",
		MUIA_Application_Version    , "$VER: NewsCoaster v1.54",
		MUIA_Application_Copyright  , "©1999-2002 Mark Harman",
		MUIA_Application_Author     , "Mark Harman",
		MUIA_Application_Description, "Newsreader",
		MUIA_Application_Base       , "NEWSCOASTER",
		MUIA_Application_SingleTask , TRUE,
		MUIA_Application_HelpFile   , "NewsCoaster:Newscoaster.guide",
		MUIA_Application_RexxHook   , &ARexxHook,

		SubWindow, wnd_main = WindowObject,
			MUIA_Window_Title,			"NewsCoaster",
			MUIA_Window_ID,				MAKE_ID('M','A','I','N'),
			MUIA_Window_ScreenTitle,	scrtitle,
			MUIA_Window_Menustrip,		menustrip=MUI_MakeObject(MUIO_MenustripNM,MenuData1,0),
			MUIA_HelpNode,					"WIN_MAIN",
			
			WindowContents, VGroup,
				Child, HGroupV,
					Child, TB_main = ToolbarObject,
						GroupFrame,
						MUIA_Toolbar_Description,		TB_main_desc,
						MUIA_Toolbar_ParseUnderscore,	TRUE,
						MUIA_Toolbar_Path,				"Progdir:icons",
						MUIA_Toolbar_ImageNormal,		"main.toolbar",
						MUIA_Toolbar_ImageGhost,		"main_G.toolbar",
						MUIA_ShortHelp,					TRUE,
						End,
					Child, HSpace(0),
					End,
				Child, HGroup,
					Child, grouplistGroup=VGroup,
						MUIA_Group_Spacing, 0,
						End,
					Child, BalanceObject, End,
					Child, messageGroup=VGroup,
						MUIA_Group_Spacing, 0,
						End,
					End,
				End,
			End,
		
		SubWindow, wnd_newnewsgroup = WindowObject,
			MUIA_Window_Title,			"New Newsgroup",
			MUIA_Window_ID,				MAKE_ID('N','N','G','R'),
			MUIA_Window_ScreenTitle,	scrtitle,
			MUIA_Window_CloseGadget,	FALSE,
			MUIA_HelpNode,					"WIN_NNG",
			
			WindowContents, VGroup,
				Child, ColGroup(2),
					Child, Label2("Newsgroup Name:"), Child, STR_nng_NAME=BetterStringObject, StringFrame, MUIA_String_Contents, "", MUIA_String_MaxLen, 64, MUIA_String_Reject, ",", MUIA_CycleChain, 1, End,
					Child, Label2("Description:"), Child, STR_nng_DESC=BetterStringObject, StringFrame, MUIA_String_Contents, "", MUIA_String_MaxLen, 64, MUIA_CycleChain, 1, End,
					Child, Label1("Default .sig:"), Child, CY_nng_DEFSIG=Cycle(CYA_nng_sigs),
					End,
				Child, ColGroup(1),
					Child, CY_nng_MAXDL=Cycle(CYA_nng_maxdl),
					Child, STR_nng_MAXDL=BetterStringObject, StringFrame, MUIA_String_Integer, 0, MUIA_String_MaxLen, 6, MUIA_String_Accept, "1234567890", MUIA_CycleChain, 1, End,
					Child, CY_nng_MAXL=Cycle(CYA_nng_maxl),
					Child, STR_nng_MAXL=BetterStringObject, StringFrame, MUIA_String_Integer, 0, MUIA_String_MaxLen, 6, MUIA_String_Accept, "1234567890", MUIA_CycleChain, 1, End,
					Child, CY_nng_MAXAGE=Cycle(CYA_nng_maxage),
					Child, STR_nng_MAXAGE=BetterStringObject, StringFrame, MUIA_String_Integer, 0, MUIA_String_MaxLen, 5, MUIA_String_Accept, "1234567890", MUIA_CycleChain, 1, End,
					Child, CY_nng_OFFLINE=Cycle(CYA_nng_offline),
					End,
				Child, ColGroup(2),
					Child, Label1("Subscribe?"), Child, CM_nng_S = CheckMark(TRUE),
					End,
				Child, ColGroup(2),
					Child, BT_nng_OKAY=SimpleButton("_Okay"),
					Child, BT_nng_CANCEL=SimpleButton("C_ancel"),
					End,
				End,
			End,

		SubWindow, wnd_editng = WindowObject,
			MUIA_Window_Title,			"Edit Newsgroup",
			MUIA_Window_ID,				MAKE_ID('E','N','G','R'),
			MUIA_Window_ScreenTitle,	scrtitle,
			MUIA_Window_CloseGadget,	FALSE,
			MUIA_HelpNode,					"WIN_ENG",
			
			WindowContents, VGroup,
				Child, ColGroup(2),
					Child, Label2("Newsgroup Name:"), Child, STR_eng_NAME=BetterStringObject, StringFrame, MUIA_String_Contents, "", MUIA_String_MaxLen, 64, MUIA_String_Reject, ",", MUIA_CycleChain, 1, End,
					Child, Label2("Description:"), Child, STR_eng_DESC=BetterStringObject, StringFrame, MUIA_String_Contents, "", MUIA_String_MaxLen, 64, MUIA_CycleChain, 1, End,
					Child, Label1("Default .sig:"), Child, CY_eng_DEFSIG=Cycle(CYA_nng_sigs),
					End,
				Child, ColGroup(1),
					Child, CY_eng_MAXDL=Cycle(CYA_nng_maxdl),
					Child, STR_eng_MAXDL=BetterStringObject, StringFrame, MUIA_String_Integer, 0, MUIA_String_MaxLen, 6, MUIA_String_Accept, "1234567890", MUIA_CycleChain, 1, End,
					Child, CY_eng_MAXL=Cycle(CYA_nng_maxl),
					Child, STR_eng_MAXL=BetterStringObject, StringFrame, MUIA_String_Integer, 0, MUIA_String_MaxLen, 6, MUIA_String_Accept, "1234567890", MUIA_CycleChain, 1, End,
					Child, CY_eng_MAXAGE=Cycle(CYA_nng_maxage),
					Child, STR_eng_MAXAGE=BetterStringObject, StringFrame, MUIA_String_Integer, 0, MUIA_String_MaxLen, 5, MUIA_String_Accept, "1234567890", MUIA_CycleChain, 1, End,
					Child, CY_eng_OFFLINE=Cycle(CYA_nng_offline),
					End,
				Child, GROUP_eng = ColGroup(2),
					Child, Label2("Last Download Date:"), Child, TXT_eng_LASTDL=TextObject, GroupFrame, MUIA_Text_Contents, "", MUIA_Text_PreParse, "\33c", MUIA_Text_SetMin, TRUE, End,
					Child, Label2("Folder Location:"), Child, TXT_eng_FOLDER=TextObject, GroupFrame, MUIA_Text_Contents, "", MUIA_Text_PreParse, "\33c", MUIA_Text_SetMin, TRUE, End,
					Child, Label1("Subscribe?"), Child, CM_eng_S = CheckMark(TRUE),
					End,
				Child, ColGroup(2),
					Child, BT_eng_OKAY=SimpleButton("_Okay"),
					Child, BT_eng_CANCEL=SimpleButton("C_ancel"),
					End,
				End,
			End,
		
		SubWindow, wnd_ngadv = WindowObject,
			MUIA_Window_Title,			"Newsgroup Advanced Settings",
			MUIA_Window_ID,				MAKE_ID('N','A','D','V'),
			MUIA_Window_ScreenTitle,	scrtitle,
			MUIA_Window_CloseGadget,	FALSE,
			
			WindowContents, VGroup,
				Child, ColGroup(3),
					Child, Label1("'Approved' Header?:"),
					Child, CM_ngadv_APPVHD = CheckMark(FALSE),
					Child, STR_ngadv_APPVHD=BetterStringObject, StringFrame, MUIA_String_Contents, "", MUIA_String_MaxLen, 64, MUIA_CycleChain, 1, End,
					Child, Label1("Alternative Name?:"),
					Child, CM_ngadv_ALTNAME = CheckMark(FALSE),
					Child, STR_ngadv_ALTNAME=BetterStringObject, StringFrame, MUIA_String_Contents, "", MUIA_String_MaxLen, 32, MUIA_CycleChain, 1, End,
					Child, Label1("Alternative Email?:"),
					Child, CM_ngadv_ALTEMAIL = CheckMark(FALSE),
					Child, STR_ngadv_ALTEMAIL=BetterStringObject, StringFrame, MUIA_String_Contents, "", MUIA_String_MaxLen, 32, MUIA_CycleChain, 1, End,
					End,
				Child, GROUP_ngadv=VGroup,
					End,
				Child, ColGroup(2),
					Child, BT_ngadv_OKAY=SimpleButton("_Okay"),
					Child, BT_ngadv_CANCEL=SimpleButton("C_ancel"),
					End,
				End,
			End,
		
		SubWindow, wnd_joinmsgs = WindowObject,
			MUIA_Window_Title,			"Join Messages",
			MUIA_Window_ID,				MAKE_ID('J','M','S','G'),
			MUIA_Window_ScreenTitle,	scrtitle,
			MUIA_Window_CloseGadget,	TRUE,
			
			WindowContents, VGroup,
				Child, NListviewObject,
					MUIA_NListview_NList,			NLIST_joinmsgs_MSGS=NListObject,
						MUIA_NList_Title,				TRUE,
						MUIA_NList_DragType,			MUIV_NList_DragType_Immediate,
						MUIA_NList_DragSortable,	TRUE,
						MUIA_NList_DisplayHook,		&DisplayHook_joinmsgs,
						MUIA_NList_CompareHook,		&CompareHook_joinmsgs,
						MUIA_NList_DestructHook,	&DestructHook_joinmsgs,
						MUIA_NList_Format,			",,,,,",
						MUIA_NList_AutoVisible,		TRUE,
						MUIA_NList_MinColSortable,	0,
						End,
					End,
				Child, ColGroup(2),
					Child, Label2("Subject:"), Child, STR_joinmsgs_SUBJECT=BetterString("",1024),
					End,
				Child, ColGroup(2),
					Child, BT_joinmsgs_JOIN=SimpleButton("_Join"),
					Child, BT_joinmsgs_CANCEL=SimpleButton("C_ancel"),
					End,
				End,
			End,

		SubWindow, wnd_account = WindowObject,
			MUIA_Window_Title,			"Program Settings",
			MUIA_Window_ID,				MAKE_ID('A','C','C','S'),
			MUIA_Window_ScreenTitle,	scrtitle,
			MUIA_Window_CloseGadget,	TRUE,
			MUIA_HelpNode,					"WIN_ACC",
			
			WindowContents, VGroup,
				
				Child, pages_account=RegisterGroup(Pages_acc),
					MUIA_Register_Frame, TRUE,
					MUIA_CycleChain, 1,
					//page 1
					Child, VGroup,
						Child, ColGroup(2),
							Child, Label2("Your Name"), Child, STR_acc_NAME=BetterString("",64),
							Child, Label2("Email for Posting"), Child, STR_acc_EMAIL=BetterString("",64),
							Child, Label2("Real Email for Emailing"), Child, STR_acc_REALEMAIL=BetterString("",64),
							Child, Label2("Organisation"), Child, STR_acc_ORG=BetterString("",64),
							End,
						Child, ColGroup(4),
							Child, Label1("Time Zone:"), Child, CY_acc_TIMEZONE=Cycle(CYA_acc_timezone),
							Child, Label1("Date Display Format:"), Child, CY_acc_DATEFORMAT=Cycle(CYA_acc_dateformat),
							End,

						Child, ColGroup(4),
							Child, Label1("Add Adjustment for DST?:"), Child, CM_acc_BST = CheckMark(FALSE),
							Child, Label1("Use Locale Prefs?:"), Child, CM_acc_USELOCALETZ=CheckMark(FALSE),

							Child, Label1("Always Check for Duplicates?:"), Child, CM_acc_CHECKFORDUPS = CheckMark(FALSE),
							Child, Label1("Delete Header if Body Not Avail.?:"), Child, CM_acc_DELONLINE = CheckMark(TRUE),

							Child, Label1("Don't Show From/Subject When d/l?:"), Child, CM_acc_QUIETDL = CheckMark(FALSE),
							Child, Label1("Switch Groups When d/l?:"), Child, CM_acc_VGROUPDL = CheckMark(FALSE),

							Child, Label1("Don't Confirm When Deleting?:"), Child, CM_acc_NOCONFIRMDEL = CheckMark(FALSE),
							Child, Label1("Always Confirm on Quit?:"), Child, CM_acc_CONFIRMQUIT = CheckMark(TRUE),

							Child, Label1("Logging Enabled?:"), Child, CM_acc_LOGGING = CheckMark(FALSE),
							Child, Label1("Delete Log on Startup?:"), Child, CM_acc_LOGDEL = CheckMark(TRUE),

							//Child, HSpace(0),
							End,
						End,
					//page 2
					Child, VGroup,
						Child, NListviewObject,
							MUIA_NListview_NList,			NLIST_acc_SERVERS=NListObject,
								MUIA_NList_Title,				TRUE,
								MUIA_NList_DragType,			MUIV_NList_DragType_Immediate,
								MUIA_NList_DragSortable,	TRUE,
								MUIA_NList_DisplayHook,		&DisplayHook_servers,
								MUIA_NList_DestructHook,	&DestructHook_servers,
								MUIA_NList_Format,			",,,,,",
								MUIA_NList_MinColSortable,	0,
								End,
							End,
						Child, ColGroup(5),
							Child, BT_acc_ADDSERVER=SimpleButton("_New Server"),
							Child, BT_acc_EDITSERVER=SimpleButton("_Edit Server"),
							Child, BT_acc_MAKEDEFSERVER=SimpleButton("Make De_fault"),
							Child, BT_acc_MAKEPOSTSERVER=SimpleButton("Use for _Posting"),
							Child, BT_acc_DELETESERVER=SimpleButton("_Delete Server"),
							End,
						Child, ColGroup(3),
							Child, BT_acc_GETGROUPS=SimpleButton("Get Groups"),
							Child, BT_acc_GETNEWGROUPS=SimpleButton("Get New Groups"),
							Child, BT_acc_GROUPMAN=SimpleButton("Groups Manager"),
							End,
						Child, ColGroup(2),
							Child, Label2("SMTP (Mail) Server"),
								Child, STR_acc_SMTP=BetterString("",64),
							End,
						End,
					//page 3
					Child, VGroup,
						Child, ColGroup(2),
							Child, Label2("Followup Attributation Line:"), Child, STR_acc_FOLLOWUPTEXT=BetterString("",128),
								Child, Label2("Charset Converter"),
								Child, POP_acc_CHARSETWRITE = PopaslObject,
									MUIA_Popstring_String, STR_acc_CHARSETWRITE=BetterString("",100),
									MUIA_Popstring_Button, PopButton(MUII_PopFile),
									MUIA_Popobject_ObjStrHook, &ObjStrAcc3Hook,
									ASLFR_TitleText, "Please Select a Charset File",
									ASLFR_Flags1, FRF_DOPATTERNS,
									ASLFR_InitialPattern, "#?.charset",
									End,
								End,
						Child, ColGroup(2),
							Child, CY_acc_SIG=Cycle(CYA_acc_sigs),
							Child, BT_acc_READSIG=SimpleButton("_Read From File"),
							End,
						Child, HGroup,
							MUIA_Group_Spacing, 0,
							Child, ED_acc_SIG = (Object*)NewObject(editor_mcc->mcc_Class, NULL,
								MUIA_TextEditor_Slider, SLD_acc_SIG,
								MUIA_CycleChain, 1,
								End,
							Child, SLD_acc_SIG,
							End,
						Child, ColGroup(4),
							Child, Label2("Line Length:"), Child, STR_acc_LINELENGTH=BetterStringObject, StringFrame, MUIA_String_Integer, 0, MUIA_String_MaxLen, 3, MUIA_String_Accept, "1234567890", MUIA_CycleChain, 1, End,
							Child, Label1("Auto. Rewrap"), Child, CM_acc_REWRAP = CheckMark(TRUE),
							End,
						Child, ColGroup(2),
							Child, Label1("Use 'X-No-Archive' Header?"), Child, CY_acc_XNO=Cycle(CYA_acc_xno),
							End,
						Child, ColGroup(4),
							Child, Label1("Use Shortened X-Newsreader Header:"), Child, CM_acc_XNEWS = CheckMark(FALSE),
							Child, Label1("Snip .sig?"), Child, CM_acc_SNIPSIG = CheckMark(FALSE),
							End,
						End,
					//page 4
					Child, VGroup,
						Child, ColGroup(5),
							Child, Label1("Header"),
							Child, CY_acc_READHEADER=Cycle(CYA_acc_readheader),
							Child, STR_acc_READHEADER=BetterString("",READHEADER_LEN),
							Child, Label2("Multiple View Windows?"),
							Child, CM_acc_MULTIPLEVWS = CheckMark(FALSE),
							End,
						Child, ColGroup(2),
							Child, FreeLabel("2nd Level Quoting"),
							Child, PEN_acc_TEXT_QUOTE2 = PoppenObject,
								MUIA_CycleChain, 1,
								MUIA_Window_Title, "2nd Level Quoted Text"),
							Child, FreeLabel("Coloured"),
							Child, PEN_acc_TEXT_COL = PoppenObject,
								MUIA_CycleChain, 1,
								MUIA_Window_Title, "Coloured Text"),
							End,
						End,
					//page 5
					Child, VGroup,
						Child, ColGroup(2),
							Child, Label2("Flags"), Child, CM_acc_LISTFLAGS = CheckMark(TRUE),
							Child, Label2("Subject"), Child, CM_acc_LISTSUBJECT = CheckMark(TRUE),
							Child, Label2("Date"), Child, CM_acc_LISTDATE = CheckMark(TRUE),
							Child, Label2("From/Newsgroup"), Child, CM_acc_LISTFROMGROUP = CheckMark(TRUE),
							Child, Label2("Size"), Child, CM_acc_LISTSIZE = CheckMark(TRUE),
							Child, Label2("# of Lines"), Child, CM_acc_LISTLINES = CheckMark(TRUE),
							End,
						End,
					//page 6
					Child, VGroup,
						Child, NListviewObject,
							MUIA_NListview_NList,			NLIST_acc_MIMEPREFS=NListObject,
								MUIA_NList_Title,				TRUE,
								MUIA_NList_DragSortable,	TRUE,
								MUIA_NList_DragType,			MUIV_NList_DragType_Immediate,
								MUIA_NList_DisplayHook,		&DisplayHook_mimeprefs,
								MUIA_NList_DestructHook,	&DestructHook_mimeprefs,
								MUIA_NList_Format,			",",
								End,
							End,
						Child, VGroup,
							Child, ColGroup(4),
								Child, Label2("MIME _Type"),
								Child, POP_acc_MIME = PopobjectObject,
									MUIA_Popstring_String, STR_acc_MIME=BetterString("",32),
									MUIA_Popstring_Button, PopButton(MUII_PopUp),
									MUIA_Popobject_StrObjHook, &StrObjHook,
									MUIA_Popobject_ObjStrHook, &ObjStrAccHook,
									MUIA_Popobject_WindowHook, &WindowHook,
									MUIA_Popobject_Object, LIST_acc_MIME = ListviewObject,
										MUIA_Listview_List, ListObject,
											InputListFrame,
											MUIA_List_SourceArray, POPA_write_mime,
											End,
										End,
									End,
								Child, Label2("_Viewer"),
								Child, POP_acc_MIMEVIEW = PopaslObject,
									MUIA_Popstring_String, STR_acc_MIMEVIEW=BetterString("",MAXFILENAME),
									MUIA_Popstring_Button, PopButton(MUII_PopFile),
									MUIA_Popobject_ObjStrHook, &ObjStrAcc2Hook,
									ASLFR_TitleText, "Please Select a Viewer",
									End,
								End,
							Child, ColGroup(2),
								Child, Label2("De_fault Viewer"),
								Child, POP_acc_MIMEDEF = PopaslObject,
									MUIA_Popstring_String, STR_acc_MIMEDEF=BetterString("",MAXFILENAME),
									MUIA_Popstring_Button, PopButton(MUII_PopFile),
									MUIA_Popobject_ObjStrHook, &ObjStrAcc3Hook,
									ASLFR_TitleText, "Please Select a Viewer",
									End,
								End,
							Child, ColGroup(2),
								Child, BT_acc_MIMENEW=SimpleButton("_New"),
								Child, BT_acc_MIMEDEL=SimpleButton("_Delete"),
								End,
							End,
						End,
					End,
				
				Child, ColGroup(2),
					Child, BT_acc_OKAY=SimpleButton("_Okay"),
					Child, BT_acc_CANCEL=SimpleButton("C_ancel"),
					End,
				
				End,
			End,
		
		SubWindow, wnd_servers = WindowObject,
			MUIA_Window_Title,			"Server",
			MUIA_Window_ID,				MAKE_ID('S','E','R','V'),
			MUIA_Window_ScreenTitle,	scrtitle,
			MUIA_Window_CloseGadget,	FALSE,
			
			WindowContents, VGroup,
				Child, ColGroup(4),
					Child, Label2("NNTP (News) Server"), Child, STR_acc_NNTP=BetterString("",64),
					Child, Label2("Port"), Child, STR_acc_PORT=BetterStringObject, StringFrame, MUIA_String_Integer, 119, MUIA_String_MaxLen, 4, MUIA_String_Accept, "1234567890", MUIA_CycleChain, 1, End,
					End,
				Child, ColGroup(6),
					Child, Label1("Use NNTP-Auth?"), Child, CM_acc_AUTH = CheckMark(FALSE),
					Child, Label2("User"), Child, STR_acc_USER=BetterString("",64),
					Child, Label2("Password"), Child, STR_acc_PASS=BetterStringObject, StringFrame, MUIA_String_Contents, "", MUIA_String_MaxLen, 64, MUIA_String_Secret, TRUE, MUIA_CycleChain, 1, End,
					End,
				Child, ColGroup(2),
					Child, BT_server_OKAY=SimpleButton("_Okay"),
					Child, BT_server_CANCEL=SimpleButton("C_ancel"),
					End,
				End,
			End,
		
		SubWindow, wnd_killfile = WindowObject,
			MUIA_Window_Title,			"KillFile Settings",
			MUIA_Window_ID,				MAKE_ID('K','I','L','L'),
			MUIA_Window_ScreenTitle,	scrtitle,
			MUIA_Window_CloseGadget,	TRUE,
			MUIA_HelpNode,					"WIN_KILLFILE",
			
			WindowContents, VGroup,
				Child, NListviewObject,
					MUIA_NListview_NList,			NLIST_acc_KILLFILE=NListObject,
						MUIA_NList_Title,				TRUE,
						MUIA_NList_DragType,			MUIV_NList_DragType_Immediate,
						MUIA_NList_DragSortable,	TRUE,
						MUIA_NList_DisplayHook,		&DisplayHook_killfile,
						MUIA_NList_DestructHook,	&DestructHook_killfile,
						MUIA_NList_Format,			",,,,,,,,",
						MUIA_NList_MinColSortable,	0,
						End,
					End,
				Child, ColGroup(2),
					Child, Label2("If the Header:"),
					Child, STR_acc_NEWKILLHEAD=BetterStringObject, StringFrame, MUIA_String_Contents, "", MUIA_String_MaxLen, 63, MUIA_CycleChain, 1, End,
					//Child, Label2("Text to Kill:"),
					Child, CY_acc_MATCHKILL=Cycle(CYA_acc_matchkill),
					Child, STR_acc_NEWKILLTEXT=BetterStringObject, StringFrame, MUIA_String_Contents, "", MUIA_String_MaxLen, 256, MUIA_CycleChain, 1, End,
					Child, Label2("in the Newsgroups:"),
					Child, STR_acc_NEWKILLGROUP=BetterStringObject, StringFrame, MUIA_String_Contents, "", MUIA_String_MaxLen, 64, MUIA_String_Reject, ",", MUIA_CycleChain, 1, End,
					End,
				Child, ColGroup(4),
					Child, Label("then.."),
					Child, CY_acc_ACTIONKILL=Cycle(CYA_acc_actionkill),
					Child, Label1("Skip Rest?"),
					Child, CM_acc_SKIPKILL=CheckMark(TRUE),
					End,
				Child, HGroup,
					Child, CY_acc_EXPIREKILL=Cycle(CYA_acc_expirekill),
					Child, STR_acc_EXPIREKILL=BetterStringObject, StringFrame, MUIA_String_Integer, 0, MUIA_String_MaxLen, 5, MUIA_String_Accept, "1234567890", MUIA_CycleChain, 1, End,
					End,
				//Child, CY_acc_TYPEKILL=Cycle(CYA_acc_typekill),
				Child, ColGroup(2),
					Child, ColGroup(2),
						Child, BT_acc_NEWKILL=SimpleButton("_New"),
						Child, BT_acc_NEWKILLADD=SimpleButton("_Add/Replace"),
						Child, BT_acc_DUPKILL=SimpleButton("Du_plicate"),
						Child, BT_acc_DELKILL=SimpleButton("_Delete"),
						End,
					Child, ColGroup(2),
						Child, Label1("'Advert' KillFile?"),
						Child, CM_acc_SIZEKILL=CheckMark(FALSE),
						End,
					End,
				End,
			End,
			
		SubWindow, wnd_groupman = WindowObject,
			MUIA_Window_Title,			"Group Manager",
			MUIA_Window_ID,				MAKE_ID('G','M','A','N'),
			MUIA_Window_ScreenTitle,	scrtitle,
			MUIA_HelpNode,					"WIN_GMAN",
			
			WindowContents, VGroup,
				Child, NListviewObject,
					MUIA_NListview_NList,			NLIST_groupman=NListObject,
						MUIA_NList_DestructHook,	&DestructHook_groupman,
						End,
					End,
				Child, ColGroup(2),
					Child, Label2("Find:"), Child, STR_groupman_FIND=BetterString("",64),
					End,
				//Child, ColGroup(5),
				Child, ColGroup(2),
					Child, BT_groupman_SUB=SimpleButton("_Subscribe"),
					Child, BT_groupman_GET=SimpleButton("_Download Group List"),
					//Child, BT_groupman_SORT=SimpleButton("S_ort Groups"),
					//Child, BT_groupman_WRITE=SimpleButton("_Write List"),
					//Child, BT_groupman_CLOSE=SimpleButton("_Close Window"),
					End,
				End,
			End,
		
		SubWindow, wnd_search = WindowObject,
			MUIA_Window_Title,			"Search",
			MUIA_Window_ID,				MAKE_ID('S','E','A','R'),
			MUIA_Window_ScreenTitle,	scrtitle,
			MUIA_HelpNode,					"WIN_SEARCH",
			
			WindowContents, VGroup,
				Child, VGroup,
					MUIA_Group_Spacing, 0,
					MUIA_VertWeight, 100,
					Child, VGroup,
						Child, NListviewObject,
							MUIA_NListview_NList,			NLIST_search_NG=NListObject,
								MUIA_NList_Title,				TRUE,
								MUIA_NList_MultiSelect,		MUIV_NList_MultiSelect_Default,
								MUIA_NList_DisplayHook,		&DisplayHook_simpleglist,
								MUIA_NList_DestructHook,	&DestructHook_groupdata,
								End,
							End,
						Child, VGroup,
							Child, ColGroup(2),
								Child, Label1("Search in:"), Child, CY_search_WHERE=Cycle(CYA_search_where),
								End,
							Child, ColGroup(4),
								Child, Label2("Search for:"), Child, STR_search_WHAT=BetterString("",64),
								Child, Label1("Case-sensitive?:"), Child, CM_search_CASESENS=CheckMark(FALSE),
								End,
							End,
						End,
					End,
				Child, BalanceObject, End,
				Child, VGroup,
					MUIA_Group_Spacing, 0,
					MUIA_VertWeight, 100,
					Child, NListviewObject,
						MUIA_NListview_NList,			NLIST_search_RES=NListObject,
							MUIA_NList_Title,				TRUE,
							MUIA_NList_MultiSelect,		MUIV_NList_MultiSelect_Default,
							MUIA_NList_DragType,			MUIV_NList_DragType_None,
							MUIA_NList_DisplayHook,		&DisplayHook_search,
							MUIA_NList_CompareHook,		&CompareHook_search,
							MUIA_NList_DestructHook,	&DestructHook_search,
							MUIA_NList_Format,			",,,,,",
							MUIA_NList_AutoVisible,		TRUE,
							MUIA_NList_MinColSortable,	0,
							End,
						End,
					Child, BT_search_START=SimpleButton("Start Search"),
					End,
				End,
			End,

		SubWindow, wnd_stats = WindowObject,
			MUIA_Window_Title,			"Statistics",
			MUIA_Window_ID,				MAKE_ID('S','T','A','T'),
			MUIA_Window_ScreenTitle,	scrtitle,
			
			WindowContents, VGroup,
				Child, VGroup,
					MUIA_Group_Spacing, 0,
					MUIA_VertWeight, 100,
					Child, VGroup,
						Child, NListviewObject,
							MUIA_NListview_NList,			NLIST_stats_NG=NListObject,
								MUIA_NList_Title,				TRUE,
								MUIA_NList_MultiSelect,		MUIV_NList_MultiSelect_Default,
								MUIA_NList_DisplayHook,		&DisplayHook_simpleglist,
								MUIA_NList_DestructHook,	&DestructHook_groupdata,
								End,
							End,
						Child, VGroup,
							Child, ColGroup(2),
								Child, Label1("Type:"), Child, CY_stats_WHAT=Cycle(CYA_stats_what),
								End,
							End,
						End,
					End,
				Child, BalanceObject, End,
				Child, VGroup,
					MUIA_Group_Spacing, 0,
					MUIA_VertWeight, 100,
					Child, NListviewObject,
						MUIA_NListview_NList,			NLIST_stats_RES=NListObject,
							MUIA_NList_DisplayHook,		&DisplayHook_stats,
							MUIA_NList_DestructHook,	&DestructHook_stats,
							MUIA_NList_CompareHook,		&CompareHook_stats,
							MUIA_NList_MultiSelect,		MUIV_NList_MultiSelect_Default,
							MUIA_NList_Title,				TRUE,
							MUIA_NList_Format,			",",
							MUIA_NList_AutoVisible,		TRUE,
							End,
						End,
					Child, BT_stats_START=SimpleButton("Start"),
					End,
				End,
			End,

		SubWindow, wnd_choice = WindowObject,
			MUIA_Window_Title,			"Message",
			MUIA_Window_ID,				MAKE_ID('M','E','S','S'),
			MUIA_Window_ScreenTitle,	scrtitle,
			
			WindowContents, VGroup,
				Child, NListviewObject,
					MUIA_NListview_NList,			NLIST_choice=NListObject,
						End,
					End,
				Child, ColGroup(3),
					Child, BT_choice_SAVE=SimpleButton("_Save"),
					Child, BT_choice_DISP=SimpleButton("_Display"),
					Child, BT_choice_CANC=SimpleButton("C_ancel"),
					End,
				End,
			End,
		
		SubWindow, wnd_newuser = WindowObject,
			MUIA_Window_Title,			"New User",
			MUIA_Window_ID,				MAKE_ID('N','U','S','R'),
			MUIA_Window_ScreenTitle,	scrtitle,
			
			WindowContents, VGroup,
				Child, TXT_newuser_INFO=TextObject, GroupFrame, MUIA_Text_Contents, "Create New User - see the 'Users'\nsection in the documentation for more\ndetails. If you are running NewsCoaster\nfor the first time, you must set up a\nuser for yourself. Please see the\n'Configuration' section in the\ndocumentation for more details.", MUIA_Text_PreParse, "\33c", MUIA_Text_SetMin, TRUE, End,
				Child, ColGroup(2),
					Child, ColGroup(2),
						Child, Label2("User Name:"), Child, STR_newuser_USER=BetterString("",9),
						Child, Label2("Password:"), Child, STR_newuser_PASS=BetterStringObject, StringFrame, MUIA_String_MaxLen, 9, MUIA_CycleChain, 1, MUIA_String_Secret, TRUE, End,
						Child, Label2("News Directory:"),
						Child, POP_newuser_DATALOC = PopaslObject,
							MUIA_Popstring_String, STR_newuser_DATALOC=BetterString("PROGDIR:",300),
							MUIA_Popstring_Button, PopButton(MUII_PopFile),
							MUIA_Popobject_ObjStrHook, &ObjStrNewuserHook,
							ASLFR_TitleText, "Please Select a Directory to Store News..",
							End,
						End,
					Child, ColGroup(2),
						Child, Label1("Supervisor?"), Child, CM_newuser_SUP=CheckMark(TRUE),
						Child, Label1("Use Password?"), Child, CM_newuser_PASS=CheckMark(FALSE),
						Child, Label1("Copy Prefs?"), Child, CM_newuser_COPYPREFS=CheckMark(FALSE),
						End,
					End,
				Child, ColGroup(2),
					Child, BT_newuser_OKAY=SimpleButton("_Okay"),
					Child, BT_newuser_CANCEL=SimpleButton("C_ancel"),
					End,
				End,
			End,

		SubWindow, wnd_users = WindowObject,
			MUIA_Window_Title,			"Users",
			MUIA_Window_ID,				MAKE_ID('U','S','E','R'),
			MUIA_Window_ScreenTitle,	scrtitle,
			
			WindowContents, VGroup,
				Child, NListviewObject,
					MUIA_NListview_NList,			NLIST_users_LIST=NListObject,
						MUIA_NList_DisplayHook,		&DisplayHook_users,
						MUIA_NList_DestructHook,	&DestructHook_users,
						MUIA_NList_CompareHook,		&CompareHook_users,
						MUIA_NList_MultiSelect,		FALSE,
						MUIA_NList_Title,				TRUE,
						MUIA_NList_Format,			",,,",
						MUIA_NList_AutoVisible,		TRUE,
						End,
					End,
				Child, ColGroup(2),
					Child, BT_users_NEW=SimpleButton("_Add New User"),
					Child, BT_users_DELETE=SimpleButton("_Delete User"),
					End,
				End,
			End,

		SubWindow, wnd_login = WindowObject,
			MUIA_Window_Title,			"User Login",
			MUIA_Window_ID,				MAKE_ID('U','L','O','G'),
			MUIA_Window_ScreenTitle,	scrtitle,
			
			WindowContents, VGroup,
				Child, ColGroup(2),
					Child, Label2("User Name:"), Child, STR_login_USER=BetterString("",USER_LEN+1),
					Child, Label2("Password:"), Child, STR_login_PASS=BetterStringObject, StringFrame, MUIA_String_MaxLen, USER_LEN+1, MUIA_CycleChain, 1, MUIA_String_Secret, TRUE, End,
					End,
				Child, ColGroup(2),
					Child, BT_login_OKAY=SimpleButton("_Okay"),
					Child, BT_login_CANCEL=SimpleButton("C_ancel"),
					End,
				End,
			End,

		SubWindow, wnd_cpwd = WindowObject,
			MUIA_Window_Title,			"Change Password",
			MUIA_Window_ID,				MAKE_ID('C','P','W','D'),
			MUIA_Window_ScreenTitle,	scrtitle,
			
			WindowContents, VGroup,
				Child, TXT_cpwd_INFO=TextObject, GroupFrame, MUIA_Text_Contents, "Please enter a new password,\nor press cancel to leave it unchanged.", MUIA_Text_PreParse, "\33c", MUIA_Text_SetMin, TRUE, End,
				Child, ColGroup(4),
					Child, Label2("Password:"), Child, STR_cpwd_PASS=BetterStringObject, StringFrame, MUIA_String_MaxLen, 9, MUIA_CycleChain, 1, MUIA_String_Secret, TRUE, End,
					Child, Label1("Use Password?"), Child, CM_cpwd_PASS=CheckMark(FALSE),
					End,
				Child, ColGroup(2),
					Child, BT_cpwd_OKAY=SimpleButton("_Okay"),
					Child, BT_cpwd_CANCEL=SimpleButton("C_ancel"),
					End,
				End,
			End,
		
		SubWindow, wnd_about = WindowObject,
			MUIA_Window_Title,			"About...",
			MUIA_Window_ID,				MAKE_ID('A','B','T','P'),
			
			WindowContents, VGroup,
				Child, TextObject, GroupFrame, MUIA_Text_Contents, abouttext, End,
				Child, TextList(TEXT_About),
				Child, BT_about_OKAY=SimpleButton("_Okay"),
				End,
			End,
		
		End;

	if (!app)
	{
		fail(app,"Failed to create Application.");
		return 0;
	}
	
	grouplistGroup_NLIST = VGroup,
						Child, NListviewObject,
							MUIA_NListview_NList,			NLIST_groupdata=NListObject,
								MUIA_NList_Title,				TRUE,
								MUIA_NList_DragType,			MUIV_NList_DragType_Immediate,
								MUIA_NList_DragSortable,	TRUE,
								MUIA_NList_DisplayHook,		&DisplayHook_groupdata,
								MUIA_NList_CompareHook,		&CompareHook_groupdata,
								MUIA_NList_DestructHook,	&DestructHook_groupdata,
								MUIA_NList_Format,			",,,",
								MUIA_NList_AutoVisible,		TRUE,
								MUIA_NList_MinColSortable,	0,
								End,
							End,
						End;
	
	grouplistGroup_LISTTREE = VGroup,
						Child, LISTVIEW_groupdata=NListviewObject,
							MUIA_NListview_NList,			LISTTREE_groupdata=NListtreeObject,
								InputListFrame,
								MUIA_NListtree_EmptyNodes,		TRUE,
								MUIA_NListtree_Title,			TRUE,
								MUIA_NListtree_DisplayHook,	&DisplayHook_groupdatatree,
								MUIA_NListtree_DestructHook,	&DestructHook_groupdatatree,
								MUIA_NListtree_Format,			",,,",
								MUIA_NListtree_DoubleClick,	MUIV_NListtree_DoubleClick_Tree,
								MUIA_NListtree_DragDropSort,	TRUE,
								MUIA_NList_MinColSortable,		0,
								End,
							End,
						End;

	messageGroup_NLIST = VGroup,
						Child, NLISTVIEW_messagelistdata=NListviewObject,
							MUIA_NListview_NList,	NLIST_messagelistdata=NListObject,
								MUIA_NList_Title,				TRUE,
								MUIA_NList_MultiSelect,		MUIV_NList_MultiSelect_Default,
								MUIA_NList_DragType,			MUIV_NList_DragType_None,
								MUIA_NList_DisplayHook,		&DisplayHook_messagelistdata,
								MUIA_NList_CompareHook,		&CompareHook_messagelistdata,
								MUIA_NList_DestructHook,	&DestructHook_messagelistdata,
								MUIA_NList_Format,			",,,,,",
								MUIA_NList_AutoVisible,		TRUE,
								MUIA_NList_MinColSortable,	0,
								End,
							End,
						End;

	messageGroup_LISTTREE = VGroup,
						Child, LISTTREEVIEW_messagelistdata=NListviewObject,
							MUIA_NListview_NList,			LISTTREE_messagelistdata=NListtreeObject,
								InputListFrame,
								MUIA_NListtree_Title,			TRUE,
								MUIA_NListtree_MultiSelect,	MUIV_NListtree_MultiSelect_Default,
								MUIA_NList_DragType,				MUIV_NList_DragType_None,
								MUIA_NListtree_EmptyNodes,		TRUE,
								MUIA_NListtree_DisplayHook,	&DisplayHook_messagelistdatatree,
								MUIA_NListtree_DoubleClick,	MUIV_NListtree_DoubleClick_Off,
								MUIA_NListtree_DragDropSort,	FALSE,
								MUIA_NListtree_Format,			",,,,,",
								MUIA_NListtree_AutoVisible,	MUIV_NListtree_AutoVisible_FirstOpen,
								MUIA_NListtree_OpenHook,		&OpenHook_messagelistdata,
								MUIA_NList_MinColSortable,		0,
								End,
							End,
						End;
	if(grouplistGroup_LISTTREE==NULL || messageGroup_LISTTREE==NULL)
		nlisttree = FALSE;
	else
		nlisttree = TRUE;
	
	menuitem_GETNEWS=(Object *)DoMethod(menustrip,MUIM_FindUData,MEN_GETNEWS);
	menuitem_GETNEWSSINGLE=(Object *)DoMethod(menustrip,MUIM_FindUData,MEN_GETNEWSSINGLE);
	menuitem_SENDNEWS=(Object *)DoMethod(menustrip,MUIM_FindUData,MEN_SENDNEWS);
	menuitem_GETGROUPSDEF=(Object *)DoMethod(menustrip,MUIM_FindUData,MEN_GETGROUPSDEF);
	menuitem_GETNEWGROUPSDEF=(Object *)DoMethod(menustrip,MUIM_FindUData,MEN_GETNEWGROUPSDEF);
	menuitem_DISCONNECT=(Object *)DoMethod(menustrip,MUIM_FindUData,MEN_DISCONNECT);
	menuitem_VIEWGROUPS=(Object *)DoMethod(menustrip,MUIM_FindUData,MEN_VIEWGROUPS);
	menuitem_VIEWMESSAGES=(Object *)DoMethod(menustrip,MUIM_FindUData,MEN_VIEWMESSAGES);
	menuitem_UPDATEGROUPS=(Object *)DoMethod(menustrip,MUIM_FindUData,MEN_UPDATEGROUPS);
	menuitem_UPDATEINDEX=(Object *)DoMethod(menustrip,MUIM_FindUData,MEN_UPDATEINDEX);
	menuitem_UPDATEALLIND=(Object *)DoMethod(menustrip,MUIM_FindUData,MEN_UPDATEALLIND);
	menuitem_IMPORT=(Object *)DoMethod(menustrip,MUIM_FindUData,MEN_IMPORT);
	menuitem_READ=(Object *)DoMethod(menustrip,MUIM_FindUData,MEN_READ);
	menuitem_EDIT=(Object *)DoMethod(menustrip,MUIM_FindUData,MEN_EDIT);
	menuitem_SUPER=(Object *)DoMethod(menustrip,MUIM_FindUData,MEN_SUPER);
	menuitem_CANCEL=(Object *)DoMethod(menustrip,MUIM_FindUData,MEN_CANCEL);
	menuitem_DELMESS=(Object *)DoMethod(menustrip,MUIM_FindUData,MEN_DELMESS);
	menuitem_UNDELMESS=(Object *)DoMethod(menustrip,MUIM_FindUData,MEN_UNDELMESS);
	menuitem_EXP=(Object *)DoMethod(menustrip,MUIM_FindUData,MEN_EXP);
	menuitem_MOVE=(Object *)DoMethod(menustrip,MUIM_FindUData,MEN_MOVE);
	menuitem_COPY=(Object *)DoMethod(menustrip,MUIM_FindUData,MEN_COPY);
	menuitem_KILLMESS=(Object *)DoMethod(menustrip,MUIM_FindUData,MEN_KILLMESS);
	menuitem_YAMADDRESS=(Object *)DoMethod(menustrip,MUIM_FindUData,MEN_YAMADDRESS);
	menuitem_POST=(Object *)DoMethod(menustrip,MUIM_FindUData,MEN_POST);
	menuitem_FOLLOWUP=(Object *)DoMethod(menustrip,MUIM_FindUData,MEN_FOLLOWUP);
	menuitem_REPLY=(Object *)DoMethod(menustrip,MUIM_FindUData,MEN_REPLY);
	menuitem_BOTH=(Object *)DoMethod(menustrip,MUIM_FindUData,MEN_BOTH);
	menuitem_PDTHIS=(Object *)DoMethod(menustrip,MUIM_FindUData,MEN_PDTHIS);
	menuitem_MARK=(Object *)DoMethod(menustrip,MUIM_FindUData,MEN_MARK);
	menuitem_CURRENTDATE=(Object *)DoMethod(menustrip,MUIM_FindUData,MEN_CURRENTDATE);
	menuitem_USERS=(Object *)DoMethod(menustrip,MUIM_FindUData,MEN_USERS);
	//menuitem_=(Object *)DoMethod(menustrip,MUIM_FindUData,MEN_);
	
	// Help System
	set(BT_nng_OKAY,MUIA_ShortHelp,"Create the new Newsgroup for\nyou to subscribe to");
	set(BT_nng_CANCEL,MUIA_ShortHelp,"Close this window and do not\ncreate a new Newsgroup");
	set(STR_nng_NAME,MUIA_ShortHelp,"Usenet Name of the Newsgroup you\nwish to subscribe to (eg,\ncomp.sys.amiga.misc)");
	set(STR_nng_DESC,MUIA_ShortHelp,"Description of the Newsgroup\n(eg, Amiga Programming) -\nOptional");
	set(CY_nng_DEFSIG,MUIA_ShortHelp,"If you are using signatures,\nthen this one will be the\ndefault for postings to the\nnewsgroup (see menu\n'Preferences/Program Settings')");
	set(CY_nng_MAXDL,MUIA_ShortHelp,"You can limit the maximum\nnumber of messages to\ndownload each time you fetch\nnew news. If Unlimited, all\nnews since the last download\ndate will be downloaded.");
	set(CY_nng_MAXL,MUIA_ShortHelp,"You can choose not to\ndownload messages that are\nlonger than a certain number\nof lines. Alternatively, you\ncan choose to have no such\nlimit.");
	set(CY_nng_OFFLINE,MUIA_ShortHelp,"Offline viewing downloads\nentire messages for you to\nread when offline. Online\nviewing only downloads the\nheaders; the rest of the\nmessage is downloaded when\nyou go to read it (thus you\nmust be online for this).");
	set(CM_nng_S,MUIA_ShortHelp,"Only news from currently\nsubscribed to Newsgroups\nwill be downloaded when\nfetching news.");
	set(BT_eng_OKAY,MUIA_ShortHelp,"Update the parameters for\nthis Newsgroup");
	set(BT_eng_CANCEL,MUIA_ShortHelp,"Cancel these changes and\nrevert to the previous\nsettings for this Newsgroup");
	set(STR_eng_NAME,MUIA_ShortHelp,"Name of the Newsgroup you\nwish to subscribe to (eg,\ncomp.sys.amiga.misc)");
	set(STR_eng_DESC,MUIA_ShortHelp,"Description of the Newsgroup\n(eg, Amiga Programming) -\nOptional");
	set(CY_eng_DEFSIG,MUIA_ShortHelp,"If you are using signatures,\nthen this one will be the\ndefault for postings to the\nnewsgroup (see menu\n'Preferences/Program Settings')");
	set(CY_eng_MAXDL,MUIA_ShortHelp,"You can limit the maximum\nnumber of messages to\ndownload each time you fetch\nnew news. If Unlimited, all\nnews since the last download\ndate will be downloaded.");
	set(CY_eng_MAXL,MUIA_ShortHelp,"You can choose not to\ndownload messages that are\nlonger than a certain number\nof lines. Alternatively, you\ncan choose to have no such\nlimit.");
	set(TXT_eng_LASTDL,MUIA_ShortHelp,"The date and (local) time\nyou last downloaded for this\nnewsgroup (or the creation\ndate if you haven't yet\ndownloaded)");
	set(CM_eng_S,MUIA_ShortHelp,"Only news from currently\nsubscribed to Newsgroups\nwill be downloaded when\nfetching news.");
	set(BT_acc_OKAY,MUIA_ShortHelp,"Keep these changes");
	set(BT_acc_CANCEL,MUIA_ShortHelp,"Cancel these changes and\nrevert to the previous\nsettings");
	set(STR_acc_NAME,MUIA_ShortHelp,"Your name (which will appear\nin messages that you post)");
	set(STR_acc_EMAIL,MUIA_ShortHelp,"Your email address, to be used\nwhen posting news - does not\nhave to be correct, see\ndocumentation for details");
	set(STR_acc_REALEMAIL,MUIA_ShortHelp,"Your real email address, to be\nused when sending email. Must\nbe correct");
	set(STR_acc_ORG,MUIA_ShortHelp,"Your organisation (company,\nuniversity, whatever you\nwant). Can be left blank");
	set(STR_acc_NNTP,MUIA_ShortHelp,"The address of your\nnewsserver (see\ndocumentation for a list of\npublic ones)");
	set(STR_acc_PORT,MUIA_ShortHelp,"The port to use to connect to\nthis newsserver (will usually\nbe 119)");
	set(STR_acc_NNTPPOST,MUIA_ShortHelp,"The address of your\nnewsserver that you wish to\nuse for posting. Leave blank\nif you wish to use the same\nserver that you read from\n(above)");
	set(STR_acc_SMTP,MUIA_ShortHelp,"The address of your SMTP\nmail server (used to send\nemail)");
	set(STR_acc_DOMAIN,MUIA_ShortHelp,"Your domain for your SMTP\nmail server");
	set(STR_acc_FOLLOWUPTEXT,MUIA_ShortHelp,"The text to be displayed when\nyou follow-up a news item.\nCodes:\n  %n - Insert Recipient's Name\n  %d - Insert Date/Time\n  %g - Insert Newsgroup\n  %m - Insert MessageID");
	set(STR_acc_CHARSETWRITE,MUIA_ShortHelp,"Select a charset convertor");
	set(CY_acc_TIMEZONE,MUIA_ShortHelp,"Set the Time-Zone that you\nlive in (so that your\nmessages appear in the right\norder in the newsgroups)");
	set(CM_acc_USELOCALETZ,MUIA_ShortHelp,"If this is ticked, then\nNewsCoaster will read the\ntimezone from your Locale\nPreferences");
	set(CM_acc_BST,MUIA_ShortHelp,"Tick this box for Daylight\nSaving Time - one hour ahead");
	set(CY_acc_DATEFORMAT,MUIA_ShortHelp,"How you wish dates to be\ndisplayed in the messages\nlist. You MUST select\n'Update All Indices' from\nthe Newsgroups menu for this\nto take effect");
	set(CM_acc_LOGGING,MUIA_ShortHelp,"Ticking this box means that\nNewsCoaster's activity will\nbe written to the text file\n'.log' in the NewsCoaster\nfolder");
	set(CM_acc_LOGDEL,MUIA_ShortHelp,"Delete the logfile everytime\nNewsCoaster starts (logfiles\ncan get rather large\notherwise)");
	set(CM_acc_VGROUPDL,MUIA_ShortHelp,"Ticking this box means that\nwhen downloading news,\nNewsCoaster will switch the\ncurrent folder to the\nnewsgroup you are downloading\nfor");
	set(CM_acc_DELONLINE,MUIA_ShortHelp,"When downloading in online\nmode, only the headers will be\ndownloaded when you fetch\nnews; the message body is\ndownloaded when you go to view\nthe message. Sometimes the\nmessage body may no longer be\navailable (especially if some\ntime has passed) - in such\ncases, the header will be\nautomatically\ndeleted if this option is\nticked.");
	set(CM_acc_CONFIRMQUIT,MUIA_ShortHelp,"If this is unticked,\nNewsCoaster will quit\nimmediately when asked to\nclosed instead of asking you\nto confirm (unless you are\nwriting a message)");
	set(CM_acc_QUIETDL,MUIA_ShortHelp,"If this box is ticked,\nNewsCoaster won't show the\nFrom and Subject line of\nmessages as it downloads them");
	set(CM_acc_NOCONFIRMDEL,MUIA_ShortHelp,"When you delete files, you\nwon't be asked for\nconfirmation if this box is\nticked. This does not apply to\n'permenant' deleting.");
	set(CM_acc_CHECKFORDUPS,MUIA_ShortHelp,"Normally NewsCoaster will only\ncheck for duplicates when it\nconsiders necessary, though\nsometimes duplicate messages\nmay repeatedly appear on a\nnewsserver's list. Checking\nthis option will ensure no\nduplicate messages are\ndownloaded, but it makes\ndownloading slower.");
	set(CY_acc_XNO,MUIA_ShortHelp,"Inserting the X-No-Archive\nheader means your message\nwill not be stored in news\narchives such as\ngroups.google.com");
	set(CM_acc_XNEWS,MUIA_ShortHelp,"Tick this box to have a\nshort X-Newsreader header");
	set(CY_acc_SIG,MUIA_ShortHelp,"Select a signature to modify");
	//set(CM_acc_USESIG,MUIA_ShortHelp,"Tick this box so that your\nsignature will appear by\ndefault when posting messages\n(which one depends on the\nNewsgroup parameters)");
	set(BT_acc_READSIG,MUIA_ShortHelp,"Insert a signature from a\nfile");
	set(ED_acc_SIG,MUIA_ShortHelp,"Type your signature here");
	set(STR_acc_LINELENGTH,MUIA_ShortHelp,"Set the linelength when\nwriting messages");
	set(CM_acc_REWRAP,MUIA_ShortHelp,"Automatically rewrap the\ntext before quoting, on\nreplies (avoids overspilling\nlines)");
	set(CM_acc_SNIPSIG,MUIA_ShortHelp,"Automatically strip the\nsignature of messages before\nreplying");
	set(CM_acc_LISTFLAGS,MUIA_ShortHelp,"Display the Flags column in\nthe message list window");
	set(CM_acc_LISTFROMGROUP,MUIA_ShortHelp,"Display the From or Newsgroup\ncolumn in the message list\nwindow");
	set(CM_acc_LISTDATE,MUIA_ShortHelp,"Display the Date column in the\nmessage list window");
	set(CM_acc_LISTSUBJECT,MUIA_ShortHelp,"Display the Subject column in\nthe message list window");
	set(CM_acc_LISTSIZE,MUIA_ShortHelp,"Display the Size column in the\nmessage list window");
	set(CM_acc_LISTLINES,MUIA_ShortHelp,"Display the Number Of Lines\ncolumn in the message list\nwindow");
	set(BT_acc_NEWKILLADD,MUIA_ShortHelp,"Add this killfile to the\nlist");
	set(BT_acc_NEWKILL,MUIA_ShortHelp,"Create a new killfile");
	set(BT_acc_DELKILL,MUIA_ShortHelp,"Delete the selected killfile");
	set(BT_acc_DUPKILL,MUIA_ShortHelp,"Duplicate the selected\nkillfile");
	set(STR_acc_NEWKILLHEAD,MUIA_ShortHelp,"The header you wish to kill\non (exact match, case\ninsensitive - includes the\ncolon). eg, 'From:'\nAlternatively, leave empty\nto kill on any header");
	set(STR_acc_NEWKILLTEXT,MUIA_ShortHelp,"If the header contains this\ntext, then the message will\nnot be downloaded (substring\nsearch, case insensitive).\neg, '@hotmail.com'");
	set(STR_acc_NEWKILLGROUP,MUIA_ShortHelp,"The newsgroups to apply this\nkillfile to (substring\nsearch, case insensitive -\nleave blank for all\nnewsgroups). eg. '',\n'comp.sys.amiga.',\n'alt.dreams.lucid'");
	set(CY_acc_EXPIREKILL,MUIA_ShortHelp,"You may set the killfile to\neither never expire, to\nexpire so many days after it\nwas created, or to expire so\nmany days after the killfile\nwas last used");
	set(STR_acc_EXPIREKILL,MUIA_ShortHelp,"The number of days to last\nfor (either after creation,\nor since last used, as\nspecified by the cycle\ngadget)");
	//set(CY_acc_TYPEKILL,MUIA_ShortHelp,"What to do if the text is\nmatched.");
	set(CY_acc_MATCHKILL,MUIA_ShortHelp,"What sort of match are we\nafter.");
	set(CY_acc_ACTIONKILL,MUIA_ShortHelp,"What to do if the killfile is\nmatched.");
	set(CM_acc_SKIPKILL,MUIA_ShortHelp,"If this killfile is matched,\nshould we carry on checking\nagainst the rest of the\nkillfiles?");
	set(CM_acc_SIZEKILL,MUIA_ShortHelp,"If this killfile is enable,\nNewsCoaster will see if the\nlast word in the subject\nline is a number, since this\nusually indicates an advert\nor other spam - see docs for\nmore details");
	set(CM_acc_MULTIPLEVWS,MUIA_ShortHelp,"When you read a new message,\ndo you want a new View window\nto open, or use an existing\none?");
	set(STR_acc_MIME,MUIA_ShortHelp,"Select the MIME Type that\nyou wish to set a viewer\nprogram for");
	set(STR_acc_MIMEVIEW,MUIA_ShortHelp,"Select the external program\nyou wish you use to view\nthis MIME Type, along with\nthe arguments - enter %s for\nthe filename");
	set(STR_acc_MIMEDEF,MUIA_ShortHelp,"Select the external program\nyou wish you use for files\nthat don't match any of the\nabove listed MIME Types, along\nwith the arguments - enter %s\nfor the filename");
	set(BT_acc_MIMENEW,MUIA_ShortHelp,"Create a new MIME Type");
	set(BT_acc_MIMEDEL,MUIA_ShortHelp,"Delete the entry for the\ncurrently selected MIME Type");

	set(BT_groupman_SUB,MUIA_ShortHelp,"Set up a new folder so that\nyou can subscribe to this\nnewsgroup");
	set(BT_groupman_GET,MUIA_ShortHelp,"Download the newsgroup list\nfrom your newsserver");
	set(STR_groupman_FIND,MUIA_ShortHelp,"Enter in some text and press\nenter, and the next\nnewsgroup containing that\ntext will be found");
	set(CY_search_WHERE,MUIA_ShortHelp,"The header you wish to\nsearch in");
	set(STR_search_WHAT,MUIA_ShortHelp,"The string you wish to\nsearch for (substring\nsearch)");
	set(CM_search_CASESENS,MUIA_ShortHelp,"Whether the search is to be\ncase-sensitive or not");
	set(CY_stats_WHAT,MUIA_ShortHelp,"What you wish to categorise\nthe frequency count by\n(Note: 'X-Newsreader' is\nslower than the others)");
	set(BT_newuser_OKAY,MUIA_ShortHelp,"Add this new user");
	set(BT_newuser_CANCEL,MUIA_ShortHelp,"Do not add this new user");
	set(STR_newuser_USER,MUIA_ShortHelp,"Username - must be between 3\nand 8 characters, and unique");
	set(STR_newuser_PASS,MUIA_ShortHelp,"Password - must be between 4\nand 8 characters. The user\ncan change it later if he\nwishes. Don't forget your\npassword!");
	set(CM_newuser_PASS,MUIA_ShortHelp,"Whether you want password\nprotection enabled or not");
	set(STR_newuser_DATALOC,MUIA_ShortHelp,"Where on your hard disk you\nwish to store the news\nmessages for this user. Must\nbe unique. If the drawer\ndoes not exist, it will be\ncreated.");
	set(CM_newuser_SUP,MUIA_ShortHelp,"Whether this user is to be a\nsupervisor. Only supervisors\ncan delete users, and add\nnew users.");
	set(CM_newuser_COPYPREFS,MUIA_ShortHelp,"If this is ticked, the\npreferences (but NOT\nnewsgroup list, .sigs or\nkillfiles) of the current\nuser will be copied to the\nnew user");
	set(BT_users_NEW,MUIA_ShortHelp,"Add a new user");
	set(BT_users_DELETE,MUIA_ShortHelp,"Delete this user!");
	set(STR_login_USER,MUIA_ShortHelp,"Please enter your username");
	set(STR_login_PASS,MUIA_ShortHelp,"Please enter your password,\nif required. If your login\nis not password protected,\nthen you can leave this\nblank.");
	set(STR_newuser_PASS,MUIA_ShortHelp,"Your new password - must be\nbetween 4 and 8 characters.\nDon't forget your new\npassword!");
	set(CM_newuser_PASS,MUIA_ShortHelp,"Whether you want password\nprotection enabled or not");
	set(BT_cpwd_OKAY,MUIA_ShortHelp,"Change your password settings");
	set(BT_cpwd_CANCEL,MUIA_ShortHelp,"Cancel these changes");
	//set(,MUIA_ShortHelp,"");

	// must be before init_data() !
	DoMethod(CM_newuser_PASS,MUIM_Notify,MUIA_Selected,TRUE,
		STR_newuser_PASS,3,MUIM_Set,MUIA_Disabled,FALSE);
	DoMethod(CM_newuser_PASS ,MUIM_Notify,MUIA_Selected,FALSE,
		STR_newuser_PASS,3,MUIM_Set,MUIA_Disabled,TRUE);
	DoMethod(BT_newuser_OKAY,MUIM_Notify,MUIA_Pressed,FALSE,
		app,2,MUIM_Application_ReturnID,NEWUSER_OKAY);
	DoMethod(BT_newuser_CANCEL,MUIM_Notify,MUIA_Pressed,FALSE,
		wnd_newuser,3,MUIM_Set,MUIA_Window_Open,FALSE);
	DoMethod(wnd_newuser,MUIM_Notify,MUIA_Window_CloseRequest,TRUE,
		wnd_newuser,3,MUIM_Set,MUIA_Window_Open,FALSE);

	DoMethod(STR_login_USER,MUIM_Notify,MUIA_String_Acknowledge,MUIV_EveryTime,
		app,2,MUIM_Application_ReturnID,LOGIN_OKAY);
	DoMethod(STR_login_PASS,MUIM_Notify,MUIA_String_Acknowledge,MUIV_EveryTime,
		app,2,MUIM_Application_ReturnID,LOGIN_OKAY);
	DoMethod(BT_login_OKAY,MUIM_Notify,MUIA_Pressed,FALSE,
		app,2,MUIM_Application_ReturnID,LOGIN_OKAY);
	DoMethod(BT_login_CANCEL,MUIM_Notify,MUIA_Pressed,FALSE,
		app,2,MUIM_Application_ReturnID,LOGIN_CANCEL);
	DoMethod(wnd_login,MUIM_Notify,MUIA_Window_CloseRequest,TRUE,
		app,2,MUIM_Application_ReturnID,LOGIN_CANCEL);

	set(STR_newuser_PASS,MUIA_Disabled,TRUE);

	BOOL success=init_data();
	if(success)
	{
	
	if(account.grouplistType==0)
		DoMethod(grouplistGroup,OM_ADDMEMBER,grouplistGroup_NLIST);
	else
		DoMethod(grouplistGroup,OM_ADDMEMBER,grouplistGroup_LISTTREE);

	DoMethod(menuitem_VIEWGROUPS,MUIM_SetUData,MEN_VIEWGROUPSLIST,MUIA_Menuitem_Checked,account.grouplistType==0);
	DoMethod(menuitem_VIEWGROUPS,MUIM_SetUData,MEN_VIEWGROUPSTREE,MUIA_Menuitem_Checked,account.grouplistType==1);

	if(account.mdata_view==0)
		DoMethod(messageGroup,OM_ADDMEMBER,messageGroup_NLIST);
	else
		DoMethod(messageGroup,OM_ADDMEMBER,messageGroup_LISTTREE);

	DoMethod(menuitem_VIEWMESSAGES,MUIM_SetUData,MEN_VIEWMESSAGESLIST,MUIA_Menuitem_Checked,account.mdata_view==0);
	DoMethod(menuitem_VIEWMESSAGES,MUIM_SetUData,MEN_VIEWMESSAGESTREE,MUIA_Menuitem_Checked,account.mdata_view==1);
	
	DoMethod(app,MUIM_Notify,MUIA_Application_DoubleStart,TRUE,
		app,2,MUIM_Application_ReturnID,APP_DOUBLESTART);

	DoMethod(wnd_main,MUIM_Notify,MUIA_Window_CloseRequest,TRUE,
		app,2,MUIM_Application_ReturnID,MUIV_Application_ReturnID_Quit);
	DoMethod(wnd_about,MUIM_Notify,MUIA_Window_CloseRequest,TRUE,
		wnd_about,3,MUIM_Set,MUIA_Window_Open,FALSE);

	DoMethod(NLIST_groupdata,MUIM_Notify,MUIA_NList_SelectChange,TRUE,
		app,2,MUIM_Application_ReturnID,NG_CHANGED);
	DoMethod(NLIST_groupdata,MUIM_Notify,MUIA_NList_DoubleClick,MUIV_EveryTime,
		app,2,MUIM_Application_ReturnID,MEN_EDITNG);
	if(nlisttree) {
		DoMethod(LISTTREE_groupdata,MUIM_Notify,MUIA_NListtree_Active,MUIV_EveryTime,
			app,2,MUIM_Application_ReturnID,NG_CHANGED);
		DoMethod(LISTTREE_groupdata,MUIM_Notify,MUIA_NListtree_DoubleClick,MUIV_EveryTime,
			app,2,MUIM_Application_ReturnID,MEN_EDITNG);
	}
	
	DoMethod(NLIST_messagelistdata,MUIM_Notify,MUIA_NList_DoubleClick,MUIV_EveryTime,
		app,2,MUIM_Application_ReturnID,MEN_READ);
	DoMethod(NLIST_messagelistdata,MUIM_Notify,MUIA_NList_TitleClick,MUIV_EveryTime,
		app,2,MUIM_Application_ReturnID,NEW_SORT);
	DoMethod(NLIST_messagelistdata,MUIM_Notify,MUIA_NList_SelectChange,TRUE,
		app,3,MUIM_CallHook,&MdataChangedHook,NULL);
	if(nlisttree) {
		DoMethod(LISTTREE_messagelistdata,MUIM_Notify,MUIA_NListtree_DoubleClick,MUIV_EveryTime,
			app,2,MUIM_Application_ReturnID,MEN_READ);
		DoMethod(LISTTREE_messagelistdata,MUIM_Notify,MUIA_NList_TitleClick,MUIV_EveryTime,
			app,2,MUIM_Application_ReturnID,NEW_SORT);
		DoMethod(LISTTREE_messagelistdata,MUIM_Notify,MUIA_NListtree_Active,MUIV_EveryTime,
			app,3,MUIM_CallHook,&MdataChangedHook,NULL);
	}

	DoMethod(TB_main,MUIM_Toolbar_Notify,TB_READ,MUIV_Toolbar_Notify_Pressed,FALSE,
		app,2,MUIM_Application_ReturnID,MEN_READ);
	DoMethod(TB_main,MUIM_Toolbar_Notify,TB_EXPORT,MUIV_Toolbar_Notify_Pressed,FALSE,
		app,2,MUIM_Application_ReturnID,MEN_EXP);
	DoMethod(TB_main,MUIM_Toolbar_Notify,TB_MOVE,MUIV_Toolbar_Notify_Pressed,FALSE,
		app,2,MUIM_Application_ReturnID,MEN_MOVE);
	DoMethod(TB_main,MUIM_Toolbar_Notify,TB_COPY,MUIV_Toolbar_Notify_Pressed,FALSE,
		app,2,MUIM_Application_ReturnID,MEN_COPY);
	DoMethod(TB_main,MUIM_Toolbar_Notify,TB_DELETE,MUIV_Toolbar_Notify_Pressed,FALSE,
		app,2,MUIM_Application_ReturnID,MEN_DELMESS);
	DoMethod(TB_main,MUIM_Toolbar_Notify,TB_KILL,MUIV_Toolbar_Notify_Pressed,FALSE,
		app,2,MUIM_Application_ReturnID,MEN_KILLMESS);
	DoMethod(TB_main,MUIM_Toolbar_Notify,TB_POST,MUIV_Toolbar_Notify_Pressed,FALSE,
		app,2,MUIM_Application_ReturnID,MEN_POST);
	DoMethod(TB_main,MUIM_Toolbar_Notify,TB_FOLLOWUP,MUIV_Toolbar_Notify_Pressed,FALSE,
		app,2,MUIM_Application_ReturnID,MEN_FOLLOWUP);
	DoMethod(TB_main,MUIM_Toolbar_Notify,TB_EDIT,MUIV_Toolbar_Notify_Pressed,FALSE,
		app,2,MUIM_Application_ReturnID,MEN_EDIT);
	DoMethod(TB_main,MUIM_Toolbar_Notify,TB_GETNEWS,MUIV_Toolbar_Notify_Pressed,FALSE,
		app,2,MUIM_Application_ReturnID,MEN_GETNEWS);
	DoMethod(TB_main,MUIM_Toolbar_Notify,TB_SENDNEWS,MUIV_Toolbar_Notify_Pressed,FALSE,
		app,2,MUIM_Application_ReturnID,MEN_SENDNEWS);
	DoMethod(TB_main,MUIM_Toolbar_Notify,TB_SEARCH,MUIV_Toolbar_Notify_Pressed,FALSE,
		app,2,MUIM_Application_ReturnID,MEN_SEARCH);
	DoMethod(TB_main,MUIM_Toolbar_Notify,TB_PROGSET,MUIV_Toolbar_Notify_Pressed,FALSE,
		app,2,MUIM_Application_ReturnID,MEN_ACCOUNT);
	DoMethod(TB_main,MUIM_Toolbar_Notify,TB_KILLFILE,MUIV_Toolbar_Notify_Pressed,FALSE,
		app,2,MUIM_Application_ReturnID,MEN_KILLFILE);

	DoMethod(BT_nng_OKAY,MUIM_Notify,MUIA_Pressed,FALSE,
		app,2,MUIM_Application_ReturnID,NNG_OKAY);
	DoMethod(BT_nng_CANCEL,MUIM_Notify,MUIA_Pressed,FALSE,
		app,2,MUIM_Application_ReturnID,NNG_CANCEL);
	DoMethod(CY_nng_MAXDL,MUIM_Notify,MUIA_Cycle_Active,0,
		STR_nng_MAXDL,3,MUIM_Set,MUIA_Disabled,TRUE);
	DoMethod(CY_nng_MAXDL,MUIM_Notify,MUIA_Cycle_Active,1,
		STR_nng_MAXDL,3,MUIM_Set,MUIA_Disabled,FALSE);
	DoMethod(CY_nng_MAXL,MUIM_Notify,MUIA_Cycle_Active,0,
		STR_nng_MAXL,3,MUIM_Set,MUIA_Disabled,TRUE);
	DoMethod(CY_nng_MAXL,MUIM_Notify,MUIA_Cycle_Active,1,
		STR_nng_MAXL,3,MUIM_Set,MUIA_Disabled,FALSE);
	DoMethod(CY_nng_MAXAGE,MUIM_Notify,MUIA_Cycle_Active,0,
		STR_nng_MAXAGE,3,MUIM_Set,MUIA_Disabled,TRUE);
	DoMethod(CY_nng_MAXAGE,MUIM_Notify,MUIA_Cycle_Active,1,
		STR_nng_MAXAGE,3,MUIM_Set,MUIA_Disabled,FALSE);
	DoMethod(CY_nng_MAXAGE,MUIM_Notify,MUIA_Cycle_Active,2,
		STR_nng_MAXAGE,3,MUIM_Set,MUIA_Disabled,FALSE);

	DoMethod(BT_eng_OKAY,MUIM_Notify,MUIA_Pressed,FALSE,
		app,2,MUIM_Application_ReturnID,ENG_OKAY);
	DoMethod(BT_eng_CANCEL,MUIM_Notify,MUIA_Pressed,FALSE,
		app,2,MUIM_Application_ReturnID,ENG_CANCEL);
	DoMethod(CY_eng_MAXDL ,MUIM_Notify,MUIA_Cycle_Active,0,
		STR_eng_MAXDL,3,MUIM_Set,MUIA_Disabled,TRUE);
	DoMethod(CY_eng_MAXDL ,MUIM_Notify,MUIA_Cycle_Active,1,
		STR_eng_MAXDL,3,MUIM_Set,MUIA_Disabled,FALSE);
	DoMethod(CY_eng_MAXL ,MUIM_Notify,MUIA_Cycle_Active,0,
		STR_eng_MAXL,3,MUIM_Set,MUIA_Disabled,TRUE);
	DoMethod(CY_eng_MAXL ,MUIM_Notify,MUIA_Cycle_Active,1,
		STR_eng_MAXL,3,MUIM_Set,MUIA_Disabled,FALSE);
	DoMethod(CY_eng_MAXAGE,MUIM_Notify,MUIA_Cycle_Active,0,
		STR_eng_MAXAGE,3,MUIM_Set,MUIA_Disabled,TRUE);
	DoMethod(CY_eng_MAXAGE,MUIM_Notify,MUIA_Cycle_Active,1,
		STR_eng_MAXAGE,3,MUIM_Set,MUIA_Disabled,FALSE);
	DoMethod(CY_eng_MAXAGE,MUIM_Notify,MUIA_Cycle_Active,2,
		STR_eng_MAXAGE,3,MUIM_Set,MUIA_Disabled,FALSE);

	DoMethod(BT_ngadv_OKAY,MUIM_Notify,MUIA_Pressed,FALSE,
		app,2,MUIM_Application_ReturnID,NGADV_OKAY);
	DoMethod(BT_ngadv_CANCEL,MUIM_Notify,MUIA_Pressed,FALSE,
		app,2,MUIM_Application_ReturnID,NGADV_CANCEL);
	DoMethod(CM_ngadv_APPVHD,MUIM_Notify,MUIA_Selected,TRUE,
		STR_ngadv_APPVHD,3,MUIM_Set,MUIA_Disabled,FALSE);
	DoMethod(CM_ngadv_APPVHD,MUIM_Notify,MUIA_Selected,FALSE,
		STR_ngadv_APPVHD,3,MUIM_Set,MUIA_Disabled,TRUE);
	DoMethod(CM_ngadv_ALTEMAIL,MUIM_Notify,MUIA_Selected,TRUE,
		STR_ngadv_ALTEMAIL,3,MUIM_Set,MUIA_Disabled,FALSE);
	DoMethod(CM_ngadv_ALTEMAIL,MUIM_Notify,MUIA_Selected,FALSE,
		STR_ngadv_ALTEMAIL,3,MUIM_Set,MUIA_Disabled,TRUE);
	DoMethod(CM_ngadv_ALTNAME,MUIM_Notify,MUIA_Selected,TRUE,
		STR_ngadv_ALTNAME,3,MUIM_Set,MUIA_Disabled,FALSE);
	DoMethod(CM_ngadv_ALTNAME,MUIM_Notify,MUIA_Selected,FALSE,
		STR_ngadv_ALTNAME,3,MUIM_Set,MUIA_Disabled,TRUE);

	DoMethod(BT_joinmsgs_JOIN,MUIM_Notify,MUIA_Pressed,FALSE,
		app,2,MUIM_Application_ReturnID,JOINMSGS_JOIN);
	DoMethod(BT_joinmsgs_CANCEL,MUIM_Notify,MUIA_Pressed,FALSE,
		app,2,MUIM_Application_ReturnID,JOINMSGS_CANCEL);
	DoMethod(wnd_joinmsgs,MUIM_Notify,MUIA_Window_CloseRequest,TRUE,
		app,2,MUIM_Application_ReturnID,JOINMSGS_CANCEL);

	DoMethod(wnd_account,MUIM_Notify,MUIA_Window_CloseRequest,TRUE,
		app,2,MUIM_Application_ReturnID,ACC_CANCEL);
	DoMethod(BT_acc_OKAY,MUIM_Notify,MUIA_Pressed,FALSE,
		app,2,MUIM_Application_ReturnID,ACC_OKAY);
	DoMethod(BT_acc_CANCEL,MUIM_Notify,MUIA_Pressed,FALSE,
		app,2,MUIM_Application_ReturnID,ACC_CANCEL);
	DoMethod(CY_acc_SIG,MUIM_Notify,MUIA_Cycle_Active,MUIV_EveryTime,
		app,2,MUIM_Application_ReturnID,ACC_CYSIG);
	DoMethod(CM_acc_USELOCALETZ,MUIM_Notify,MUIA_Selected,TRUE,
		CY_acc_TIMEZONE,3,MUIM_Set,MUIA_Disabled,TRUE);
	DoMethod(CM_acc_USELOCALETZ,MUIM_Notify,MUIA_Selected,FALSE,
		CY_acc_TIMEZONE,3,MUIM_Set,MUIA_Disabled,FALSE);

	DoMethod(CM_acc_AUTH,MUIM_Notify,MUIA_Selected,TRUE,
		STR_acc_USER,3,MUIM_Set,MUIA_Disabled,FALSE);
	DoMethod(CM_acc_AUTH,MUIM_Notify,MUIA_Selected,FALSE,
		STR_acc_USER,3,MUIM_Set,MUIA_Disabled,TRUE);
	DoMethod(CM_acc_AUTH,MUIM_Notify,MUIA_Selected,TRUE,
		STR_acc_PASS,3,MUIM_Set,MUIA_Disabled,FALSE);
	DoMethod(CM_acc_AUTH ,MUIM_Notify,MUIA_Selected,FALSE,
		STR_acc_PASS,3,MUIM_Set,MUIA_Disabled,TRUE);
	DoMethod(BT_acc_ADDSERVER,MUIM_Notify,MUIA_Pressed,FALSE,
		app,2,MUIM_Application_ReturnID,ACC_ADDSERVER);
	DoMethod(BT_acc_EDITSERVER,MUIM_Notify,MUIA_Pressed,FALSE,
		app,2,MUIM_Application_ReturnID,ACC_EDITSERVER);
	DoMethod(BT_acc_MAKEDEFSERVER,MUIM_Notify,MUIA_Pressed,FALSE,
		app,2,MUIM_Application_ReturnID,ACC_MAKEDEFSERVER);
	DoMethod(BT_acc_MAKEPOSTSERVER,MUIM_Notify,MUIA_Pressed,FALSE,
		app,2,MUIM_Application_ReturnID,ACC_MAKEPOSTSERVER);
	DoMethod(BT_acc_DELETESERVER,MUIM_Notify,MUIA_Pressed,FALSE,
		app,2,MUIM_Application_ReturnID,ACC_DELETESERVER);
	DoMethod(BT_acc_GETGROUPS,MUIM_Notify,MUIA_Pressed,FALSE,
		app,2,MUIM_Application_ReturnID,ACC_GETGROUPS);
	DoMethod(BT_acc_GETNEWGROUPS,MUIM_Notify,MUIA_Pressed,FALSE,
		app,2,MUIM_Application_ReturnID,ACC_GETNEWGROUPS);
	DoMethod(BT_acc_GROUPMAN,MUIM_Notify,MUIA_Pressed,FALSE,
		app,2,MUIM_Application_ReturnID,ACC_GROUPMAN);
	DoMethod(BT_server_OKAY,MUIM_Notify,MUIA_Pressed,FALSE,
		app,2,MUIM_Application_ReturnID,SERVER_OKAY);
	DoMethod(BT_server_CANCEL,MUIM_Notify,MUIA_Pressed,FALSE,
		app,2,MUIM_Application_ReturnID,SERVER_CANCEL);

	DoMethod(CY_acc_READHEADER,MUIM_Notify,MUIA_Cycle_Active,0,
		STR_acc_READHEADER,3,MUIM_Set,MUIA_Disabled,TRUE);
	DoMethod(CY_acc_READHEADER,MUIM_Notify,MUIA_Cycle_Active,1,
		STR_acc_READHEADER,3,MUIM_Set,MUIA_Disabled,FALSE);
	DoMethod(CY_acc_READHEADER,MUIM_Notify,MUIA_Cycle_Active,2,
		STR_acc_READHEADER,3,MUIM_Set,MUIA_Disabled,TRUE);

	DoMethod(BT_acc_READSIG,MUIM_Notify,MUIA_Pressed,FALSE,
		app,2,MUIM_Application_ReturnID,ACC_READSIG);
	DoMethod(NLIST_acc_KILLFILE,MUIM_Notify,MUIA_NList_SelectChange,TRUE,
		app,2,MUIM_Application_ReturnID,ACC_KILLCHANGED);
	DoMethod(BT_acc_NEWKILLADD,MUIM_Notify,MUIA_Pressed,FALSE,
		app,2,MUIM_Application_ReturnID,ACC_STRKILL);
	DoMethod(STR_acc_NEWKILLHEAD,MUIM_Notify,MUIA_String_Acknowledge,MUIV_EveryTime,
		app,2,MUIM_Application_ReturnID,ACC_STRKILL);
	DoMethod(STR_acc_NEWKILLTEXT,MUIM_Notify,MUIA_String_Acknowledge,MUIV_EveryTime,
		app,2,MUIM_Application_ReturnID,ACC_STRKILL);
	DoMethod(STR_acc_NEWKILLGROUP,MUIM_Notify,MUIA_String_Acknowledge,MUIV_EveryTime,
		app,2,MUIM_Application_ReturnID,ACC_STRKILL);
	DoMethod(STR_acc_EXPIREKILL,MUIM_Notify,MUIA_String_Acknowledge,MUIV_EveryTime,
		app,2,MUIM_Application_ReturnID,ACC_STRKILL);
	DoMethod(CY_acc_EXPIREKILL,MUIM_Notify,MUIA_Cycle_Active,MUIV_EveryTime,
		app,2,MUIM_Application_ReturnID,ACC_STRKILLTEMP);
	/*DoMethod(CY_acc_TYPEKILL,MUIM_Notify,MUIA_Cycle_Active,MUIV_EveryTime,
		app,2,MUIM_Application_ReturnID,ACC_STRKILLTEMP);*/
	DoMethod(CY_acc_MATCHKILL,MUIM_Notify,MUIA_Cycle_Active,MUIV_EveryTime,
		app,2,MUIM_Application_ReturnID,ACC_STRKILLTEMP);
	DoMethod(CY_acc_ACTIONKILL,MUIM_Notify,MUIA_Cycle_Active,MUIV_EveryTime,
		app,2,MUIM_Application_ReturnID,ACC_STRKILLTEMP);
	DoMethod(CM_acc_SKIPKILL,MUIM_Notify,MUIA_Selected,MUIV_EveryTime,
		app,2,MUIM_Application_ReturnID,ACC_STRKILLTEMP);
	DoMethod(BT_acc_NEWKILL,MUIM_Notify,MUIA_Pressed,FALSE,
		app,2,MUIM_Application_ReturnID,ACC_NEWKILL);
	DoMethod(BT_acc_DELKILL,MUIM_Notify,MUIA_Pressed,FALSE,
		app,2,MUIM_Application_ReturnID,ACC_DELKILL);
	DoMethod(BT_acc_DUPKILL,MUIM_Notify,MUIA_Pressed,FALSE,
		app,2,MUIM_Application_ReturnID,ACC_DUPKILL);
	DoMethod(CY_acc_EXPIREKILL,MUIM_Notify,MUIA_Cycle_Active,0,
		STR_acc_EXPIREKILL,3,MUIM_Set,MUIA_Disabled,TRUE);
	DoMethod(CY_acc_EXPIREKILL,MUIM_Notify,MUIA_Cycle_Active,1,
		STR_acc_EXPIREKILL,3,MUIM_Set,MUIA_Disabled,FALSE);
	DoMethod(CY_acc_EXPIREKILL,MUIM_Notify,MUIA_Cycle_Active,2,
		STR_acc_EXPIREKILL,3,MUIM_Set,MUIA_Disabled,FALSE);
	DoMethod(LIST_acc_MIME,MUIM_Notify,MUIA_Listview_DoubleClick,TRUE,
		POP_acc_MIME,2,MUIM_Popstring_Close,TRUE);
	DoMethod(NLIST_acc_MIMEPREFS,MUIM_Notify,MUIA_NList_Active,MUIV_EveryTime,
		app,2,MUIM_Application_ReturnID,ACC_MIMECLICK);
	DoMethod(BT_acc_MIMENEW,MUIM_Notify,MUIA_Pressed,FALSE,
		app,2,MUIM_Application_ReturnID,ACC_MIMENEW);
	DoMethod(BT_acc_MIMEDEL,MUIM_Notify,MUIA_Pressed,FALSE,
		app,2,MUIM_Application_ReturnID,ACC_MIMEDEL);
	DoMethod(STR_acc_MIME,MUIM_Notify,MUIA_String_Acknowledge,MUIV_EveryTime,
		app,2,MUIM_Application_ReturnID,ACC_MIMESTR);
	DoMethod(STR_acc_MIMEVIEW,MUIM_Notify,MUIA_String_Acknowledge,MUIV_EveryTime,
		app,2,MUIM_Application_ReturnID,ACC_MIMESTR);
	DoMethod(pages_account,MUIM_Notify,MUIA_Group_ActivePage,MUIV_EveryTime,
		app,2,MUIM_Application_ReturnID,ACC_PAGESIG);
	
	DoMethod(wnd_killfile,MUIM_Notify,MUIA_Window_CloseRequest,TRUE,
		app,2,MUIM_Application_ReturnID,KILL_CLOSE);
	
	DoMethod(STR_groupman_FIND,MUIM_Notify,MUIA_String_Acknowledge,MUIV_EveryTime,
		app,2,MUIM_Application_ReturnID,GROUPMAN_FIND);
	DoMethod(NLIST_groupman,MUIM_Notify,MUIA_NList_DoubleClick,TRUE,
		app,2,MUIM_Application_ReturnID,GROUPMAN_SUB);
	DoMethod(BT_groupman_SUB,MUIM_Notify,MUIA_Pressed,FALSE,
		app,2,MUIM_Application_ReturnID,GROUPMAN_SUB);
	DoMethod(BT_groupman_GET,MUIM_Notify,MUIA_Pressed,FALSE,
		app,2,MUIM_Application_ReturnID,GROUPMAN_GETGROUPS);
	/*DoMethod(BT_groupman_WRITE,MUIM_Notify,MUIA_Pressed,FALSE,
		app,2,MUIM_Application_ReturnID,GROUPMAN_WRITE);
	DoMethod(BT_groupman_SORT,MUIM_Notify,MUIA_Pressed,FALSE,
		app,2,MUIM_Application_ReturnID,GROUPMAN_SORT);*/
	/*DoMethod(wnd_groupman,MUIM_Notify,MUIA_Window_CloseRequest,TRUE,
		wnd_groupman,3,MUIM_Set,MUIA_Window_Open,FALSE);
	DoMethod(BT_groupman_CLOSE,MUIM_Notify,MUIA_Pressed,FALSE,
		wnd_groupman,3,MUIM_Set,MUIA_Window_Open,FALSE);*/
	DoMethod(wnd_groupman,MUIM_Notify,MUIA_Window_CloseRequest,TRUE,
		app,2,MUIM_Application_ReturnID,GROUPMAN_CLOSE);

	DoMethod(wnd_search,MUIM_Notify,MUIA_Window_CloseRequest,TRUE,
		wnd_search,3,MUIM_Set,MUIA_Window_Open,FALSE);
	DoMethod(BT_search_START,MUIM_Notify,MUIA_Pressed,FALSE,
		app,2,MUIM_Application_ReturnID,SEARCH_START);
	DoMethod(NLIST_search_RES,MUIM_Notify,MUIA_NList_DoubleClick,MUIV_EveryTime,
		app,2,MUIM_Application_ReturnID,SEARCH_MESSAGE);
	DoMethod(NLIST_search_RES,MUIM_Notify,MUIA_NList_TitleClick,MUIV_EveryTime,
		app,2,MUIM_Application_ReturnID,SEARCH_SORT);
	DoMethod(wnd_stats,MUIM_Notify,MUIA_Window_CloseRequest,TRUE,
		wnd_stats,3,MUIM_Set,MUIA_Window_Open,FALSE);
	DoMethod(BT_stats_START,MUIM_Notify,MUIA_Pressed,FALSE,
		app,2,MUIM_Application_ReturnID,STATS_START);
	DoMethod(NLIST_stats_RES,MUIM_Notify,MUIA_NList_TitleClick,MUIV_EveryTime,
		app,2,MUIM_Application_ReturnID,STATS_SORT);

	DoMethod(BT_choice_SAVE,MUIM_Notify,MUIA_Pressed,FALSE,
		app,2,MUIM_Application_ReturnID,CHOICE_SAVE);
	DoMethod(BT_choice_DISP,MUIM_Notify,MUIA_Pressed,FALSE,
		app,2,MUIM_Application_ReturnID,CHOICE_DISP);
	DoMethod(BT_choice_CANC,MUIM_Notify,MUIA_Pressed,FALSE,
		app,2,MUIM_Application_ReturnID,CHOICE_CANC);
	DoMethod(wnd_choice,MUIM_Notify,MUIA_Window_CloseRequest,TRUE,
		app,2,MUIM_Application_ReturnID,CHOICE_CANC);

	DoMethod(wnd_users,MUIM_Notify,MUIA_Window_CloseRequest,TRUE,
		wnd_users,3,MUIM_Set,MUIA_Window_Open,FALSE);
	DoMethod(BT_users_NEW,MUIM_Notify,MUIA_Pressed,FALSE,
		app,2,MUIM_Application_ReturnID,USERS_NEW);
	DoMethod(BT_users_DELETE,MUIM_Notify,MUIA_Pressed,FALSE,
		app,2,MUIM_Application_ReturnID,USERS_DELETE);
	
	DoMethod(CM_cpwd_PASS,MUIM_Notify,MUIA_Selected,TRUE,
		STR_cpwd_PASS,3,MUIM_Set,MUIA_Disabled,FALSE);
	DoMethod(CM_cpwd_PASS ,MUIM_Notify,MUIA_Selected,FALSE,
		STR_cpwd_PASS,3,MUIM_Set,MUIA_Disabled,TRUE);
	DoMethod(BT_cpwd_OKAY,MUIM_Notify,MUIA_Pressed,FALSE,
		app,2,MUIM_Application_ReturnID,CPWD_OKAY);
	DoMethod(BT_cpwd_CANCEL,MUIM_Notify,MUIA_Pressed,FALSE,
		wnd_cpwd,3,MUIM_Set,MUIA_Window_Open,FALSE);
	DoMethod(wnd_cpwd,MUIM_Notify,MUIA_Window_CloseRequest,TRUE,
		wnd_cpwd,3,MUIM_Set,MUIA_Window_Open,FALSE);

	DoMethod(BT_about_OKAY,MUIM_Notify,MUIA_Pressed,FALSE,
		wnd_about,3,MUIM_Set,MUIA_Window_Open,FALSE);

	//registration
	CheckRegist();
	registered=IsRegistered();
	if(registered) {
		regist = ReturnRegistration();
		regID=regist->OwnerID;
	}
	
	srand(clock());
	set(CY_nng_DEFSIG,MUIA_Cycle_Active,1);
	set(STR_nng_MAXDL,MUIA_Disabled,TRUE);
	set(STR_eng_MAXDL,MUIA_Disabled,TRUE);
	set(STR_nng_MAXL,MUIA_Disabled,TRUE);
	set(STR_eng_MAXL,MUIA_Disabled,TRUE);
	set(STR_nng_MAXAGE,MUIA_Disabled,TRUE);
	set(STR_eng_MAXAGE,MUIA_Disabled,TRUE);
	set(STR_ngadv_APPVHD,MUIA_Disabled,TRUE);
	set(STR_ngadv_ALTNAME,MUIA_Disabled,TRUE);
	set(STR_ngadv_ALTEMAIL,MUIA_Disabled,TRUE);
	set(CY_ngadv_SERVER,MUIA_Disabled,TRUE);
	set(CM_ngadv_SERVERPOST,MUIA_Disabled,TRUE);
	set(STR_acc_USER,MUIA_Disabled,TRUE);
	set(STR_acc_PASS,MUIA_Disabled,TRUE);
	set(STR_acc_READHEADER,MUIA_Disabled,TRUE);
	set(STR_acc_EXPIREKILL,MUIA_Disabled,TRUE);
	resetGdataActive();
	set(wnd_main,MUIA_Window_Open,TRUE);

	/*while(running) {
		do_input();
		if(running && signal)
			Wait(signal);
	}*/
	/*while(running) {
		do_input();
		if(running && signal)
			signal = Wait(signal);
	}*/
	do_input();
	do {
		if(signal)
			signal = Wait(signal);
		do_input();
	} while(running);
	
	set(wnd_main,MUIA_Window_Open,FALSE);
	
	free_data();
	
	} // end of success (for login)

	nLog("about to call MUI_DisposeObject(app)\n");
	if(app != NULL)
		MUI_DisposeObject(app);
	nLog("  MUI_DisposeObject() called\n");

	if(grouplistGroup_NLIST && account.grouplistType!=0) {
		nLog("dispose gdata nlist\n");
		MUI_DisposeObject(grouplistGroup_NLIST);
	}
	if(grouplistGroup_LISTTREE && account.grouplistType!=1) {
		nLog("dispose gdata listtree\n");
		MUI_DisposeObject(grouplistGroup_LISTTREE);
	}
	if(messageGroup_NLIST && account.mdata_view!=0) {
		nLog("dispose mdata nlist\n");
		MUI_DisposeObject(messageGroup_NLIST);
	}
	if(messageGroup_LISTTREE && account.mdata_view!=1) {
		nLog("dispose mdata listtree\n");
		MUI_DisposeObject(messageGroup_LISTTREE);
	}

	if(editor_mcc != NULL) {
		nLog("about to dispose of TextEditor Custom Class\n");
		MUI_DeleteCustomClass(editor_mcc);
	}

	nLog("about to call CloseLibrary(MUIMasterBase)\n");
	if(MUIMasterBase)
   	CloseLibrary(MUIMasterBase);
	nLog("  CloseLibrary() called\n");

	nLog("NewsCoaster finishing - closing log file\n");
	if(logFile!=NULL) {
		Close(logFile);
		logFile=NULL;
	}
	#ifdef _DEBUG
	dumpAllocs();
	#endif
	return 0;
}

int realmain() {
	int ret = 0;

	const int MINSTACK = 200000;
	int stack = askStack();

	SysBase = *((struct ExecBase **) (4L));
	if( SysBase->LibNode.lib_Version >= 37 && stack < MINSTACK ) {
		printf("Current stack is %d - increasing to %d\n",stack,MINSTACK);
		/*
		** Align the stack size to multiple of longword
		*/
		ULONG newsize = (MINSTACK + 3) & ~3;

		/*
		** Allocate the StackSwapStruct and the new stack
		*/
		g_sss = (StackSwapStruct *)AllocMem(sizeof(struct StackSwapStruct) + newsize, MEMF_PUBLIC);
		if(g_sss) {
			/*
			** Fill the StackSwapStruct
			*/
			g_sss->stk_Lower = g_sss + 1;
			g_sss->stk_Upper = ((ULONG) g_sss->stk_Lower) + newsize;
			g_sss->stk_Pointer = (APTR) g_sss->stk_Upper;

			/*
			** Swap in the new stack
			*/
			StackSwap(g_sss);

		}

		ret = realmain_2();

		/*
		** Swap the original stack back
		*/
		StackSwap(g_sss);

		/*
		** Free the stack memory, note that 'newsize' variable is
		** available again even if it is a stack variable...
		*/
		FreeMem(g_sss, sizeof(struct StackSwapStruct) + newsize);
	}
	else {
		ret = realmain_2();
	}

	return ret;
}

int main(int argc,char **argv) {
	for(int i=0;i<argc;i++) {
		if(stricmp(argv[i],"DEBUG")==0) {
			DEBUG=TRUE;
			printf("DEBUG mode activated\n");
		}
		else if(stricmp(argv[i],"FORCEPATCH1")==0) {
			FORCEPATCH1=TRUE;
			printf("FORCEPATCH1 mode activated\n");
		}
		else if(stricmp(argv[i],"TEST")==0) {
			// test mode
			int major = -1; // default to running all test sets
			int minor = -1; // default to running all in a test set
			if( i+1 < argc ) {
				major = atoi(argv[i+1]);
				if( i+2 < argc ) {
					minor = atoi(argv[i+2]);
				}
			}
			tests(major,minor);
			return 0;
		}
	}
	return realmain();
}

int wbmain(WBStartup* wbmsg) {
	return realmain();
}
