/*
    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 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;

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

const float ver=1.52;
char version[]="1.52";
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 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 *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","Date","MessageID","Content-Type","Header", "Message Body", "Entire Message",NULL
	"From","Newsgroups","Subject","MessageID","Content-Type","Header", "Message Body", "Entire Message",NULL
};
enum {
	SEARCH_FROM = 0, SEARCH_NEWSGROUPS = 1, SEARCH_SUBJECT = 2, SEARCH_MESSAGEID = 3, SEARCH_CONTENTTYPE = 4, SEARCH_HEADER = 5, SEARCH_BODY = 6, SEARCH_ALL = 7
};

/* 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;
int *server_list;

/*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];
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() {
	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);
	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);

		char filename[300] = "";
		getFilePath(filename,gdata->ID,mdata->ID);

		sprintf(helptext,
			"From: %s\nSubject: %s\nDate: %s %s\nNewsgroup: %s\nSize: %d\n# of Lines: %d\nFilename: %s%s%s%s%s\n",
			mdata->from,
			mdata->subject,
			mdata->c_date,
			mdata->c_time,
			mdata->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);
		}

		sprintf(helptext,
			"%s\n# of Messages: %d\n# of Unread Messages: %d%s%s%s\nFolder Location: %s",
			gdata->name,
			gdata->nummess,
			gdata->num_unread,
			gdata->ID < 0 ? "" : (gdata->flags[5] ? "\nOnline Reading" : "\nOffline Reading"),
			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 buffer[256]="";
	getFilePath(buffer,gdata->ID,mdata->ID);
	DeleteFile(buffer);
}

void delete_file_n(GroupData * gdata,MessageListData * mdataptr,int n) {
	char buffer[256]="";
	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) ];
	for(int i=0;i<n;i++) {
		sprintf(ptr,"%d",mdataptr[i].ID);
		DeleteFile(buffer);
	}
}

BOOL changedate(GroupData *gdata,MessageListData *mdata) {
	nLog("changedate((GroupData *)%d,(MessageListData *)%d called\n",gdata,mdata);
	char buffer[256] = "";
	char buffer2[256] = "";
	char line[MAXLINE] = "";
	getFilePath(buffer,gdata->ID,mdata->ID);
	int newID = gdata->nextmID++;
	getFilePath(buffer2,gdata->ID,newID);

	BPTR lock=Lock(buffer,ACCESS_READ);
	BPTR file=Open(buffer,MODE_OLDFILE);

	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 %s\n",mdata->c_date,mdata->c_time);
				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) {
		mdata->ID = newID;
		write_index_update(gdata,mdata);
		DeleteFile(buffer);
	}
	
	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[300]="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);

	const int bufsize=8192;
	char buffer[bufsize]="";
	char divide[1024]="";
	get(NLIST_messagelistdata,MUIA_NList_Entries,&entries);
	//archive folder
	DeleteFile(filename);
	file=Open(filename,MODE_NEWFILE);
	if(file) {
		StatusWindow statusWindow(app,"Archiving..");
		set(wnd_main,MUIA_Window_Sleep,TRUE);
		WriteWindow::sleepAll(TRUE);
		ViewWindow::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(buffer,"Archiving.. (%d/%d)",k+1,entries);
					statusWindow.setText(buffer);
				}
				DoMethod(NLIST_messagelistdata,MUIM_NList_GetEntry,k,&mdata);
				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(buffer,"\33cUnable to open file:\n%s",filename2);
					MUI_RequestA(app,0,0,"Error","_Okay",buffer,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 ) {
						//printf("%d\n",read);
						Write(file,buffer,read);
					}
					Close(file2);
					file2=NULL;
					//UnLock(lock2);
					//lock2=NULL;
					/*if(statusWindow.isAborted()==TRUE || running==FALSE)
						break;*/
					Write(file,"\n",1);
				}
			}
		}
		set(wnd_main,MUIA_Window_Sleep,FALSE);
		WriteWindow::sleepAll(FALSE);
		ViewWindow::sleepAll(FALSE);
	}
	else {
		char error[300] = "";
		sprintf(error,"Couldn't open file %s to write to.\n",filename);
		nLog(error);
		MUI_RequestA(app,0,0,"Error","_Okay",error,0);
	}
	if(file) {
		Close(file);
		file=NULL;
	}
}

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() {
	DoMethod(LISTTREE_messagelistdata,MUIM_NListtree_Remove,MUIV_NListtree_Remove_ListNode_Root,MUIV_NListtree_Remove_TreeNode_All,0);
}

void threadView() {
	if(account.mdata_view!=1)
		return;
	// takes messages from NLIST_messagelistdata, and inserts into LISTTREE_messagelistdata
	int entries = 0,k = 0,pos = 0;
	BOOL cont = FALSE;
	int skipped = 0,start = 0;
	MessageListData * mdata = NULL;
	DoMethod(NLIST_messagelistdata,MUIM_NList_Sort);
	get(NLIST_messagelistdata,MUIA_NList_Entries,&entries);
	set(wnd_main,MUIA_Window_Sleep,TRUE);
	//set(LISTTREE_messagelistdata,MUIA_NList_Quiet,TRUE);
	set(LISTTREE_messagelistdata,MUIA_NListtree_Quiet,TRUE);
	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];
		do {
			cont=FALSE;
			start=skipped;
			skipped=-1;
			for(k=start;k<entries;k++) {
				if(tnptr[k]==NULL) {
					DoMethod(NLIST_messagelistdata,MUIM_NList_GetEntry,k,&mdata);
					if(*mdata->lastref==0) {
						tnptr[k]=(MUI_NListtree_TreeNode *)DoMethod(LISTTREE_messagelistdata,MUIM_NListtree_Insert,"",mdata,MUIV_NListtree_Insert_ListNode_Root,MUIV_NListtree_Insert_PrevNode_Tail,TNF_LIST);
						cont=TRUE;
						if(skipped!=-1)
							break;
					}
					else {
						get_mdata_pos(&pos,mdata->lastref);
						if(pos==-1) {
							tnptr[k]=(MUI_NListtree_TreeNode *)DoMethod(LISTTREE_messagelistdata,MUIM_NListtree_Insert,"",mdata,MUIV_NListtree_Insert_ListNode_Root,MUIV_NListtree_Insert_PrevNode_Tail,TNF_LIST);
							cont=TRUE;
							if(skipped!=-1)
								break;
						}
						else {
							if(tnptr[pos]) {
								tnptr[k]=(MUI_NListtree_TreeNode *)DoMethod(LISTTREE_messagelistdata,MUIM_NListtree_Insert,"",mdata,tnptr[pos],MUIV_NListtree_Insert_PrevNode_Tail,TNF_LIST);
								cont=TRUE;
								if(skipped!=-1)
										break;
							}
							else
								skipped=k;
						}
					}
				}
			}
		} while(cont);
		delete [] tnptr;
	}
	DoMethod(LISTTREE_messagelistdata,MUIM_NList_ColWidth,MUIV_NList_ColWidth_All,MUIV_NList_ColWidth_Default);
	//set(LISTTREE_messagelistdata,MUIA_NList_Quiet,FALSE);
	set(LISTTREE_messagelistdata,MUIA_NListtree_Quiet,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,BOOL visible) {
	nLog("set_and_read((int)%d,(BOOL)%d) called\n",gID,visible);
	GroupData * gdata2=NULL;
	getGdataDisplayed(&gdata2);
	if(gdata2->ID != gID) {
		set_gdata(gID);
		read_index(visible);
	}
}

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

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

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,FALSE);
					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_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] = "";
	const int BUFLEN = 2 * MAXLINE;
	char buffer[BUFLEN] = "";
	char nextline[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;
	int len = 0,nlen = 0;
	Seek(file,0,OFFSET_BEGINNING);
		for(;;) {
			len = 0;
			for(;;) {
				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;
						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
					break;
				}
				len=nlen;
			}
			if(len==0)
				break;
			if(*buffer==0)
				break;
			//StripTrail(buffer,' ');
			wordFirstUpper(word1,buffer);
			if(strcmp(word1,"FROM:")==0) {
				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) {
				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_short);
				newmess->date[NEWMESS_short]=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) {
				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;

}

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[MAXFILENAME]="";
	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);
}

/*void get_refs(NewMessage * newmess,GroupData * gdata,MessageListData * mdata) {
	get_refs(newmess,gdata,mdata,GETREFS_ALL);
}*/

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[MAXFILENAME]="";
	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 filename2[256]="";
	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);
	set(NLIST_messagelistdata,MUIA_NList_Quiet,TRUE);
	set(LISTTREE_messagelistdata,MUIA_NListtree_Quiet,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(filename2,gdata->ID,mdata->ID);
						lock2=Lock(filename2,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(FALSE);
			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);
	set(NLIST_messagelistdata,MUIA_NList_Quiet,FALSE);
	set(LISTTREE_messagelistdata,MUIA_NListtree_Quiet,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[300] = "";
	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;
	char filename[256]="";
	char subfolder[256]="";
	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;
			}
			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[256]="";
	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(TRUE);
}

void save_killfile(char *filename) {
	nLog("save_killfile((char *)%s) called\n",filename);
	//save folder prefs
	char filenamenew[300] = "";
	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[MAXFILENAME]="";
	strcpy(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
	strcpy(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;
		if(i==entries-1) // not found! return default server instead
			return getDefaultServer();
	}
	return NULL;
}

void freeServerCycle() {
	if(GROUP_ngadv_SUB!=NULL) {
		DoMethod(GROUP_ngadv,OM_REMMEMBER,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 = HGroup,
		Child, Label2("Newsserver:"),
		Child, CY_ngadv_SERVER = Cycle(CYA_ngadv_server),
		Child, Label1("Default?:"),
		Child, CM_ngadv_SERVER = CheckMark(FALSE),
		//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);
	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[MAXFILENAME]="";
	strcpy(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[MAXFILENAME]="";
	//save folder prefs
	strcpy(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/folder.index");
	else if(gID==-2)
		strcpy(buffer,"NewsCoasterData:sent/folder.index");
	else if(gID==-3)
		strcpy(buffer,"NewsCoasterData:deleted/folder.index");
	else
		sprintf(buffer,"NewsCoasterData:folder_%d/folder.index",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
	strcpy(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[MAXFILENAME]="";
	strcpy(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");
	char filename[300] = "";
	GroupData * gdata = NULL;
	strcpy(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[MAXFILENAME]="";
	strcpy(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;
	strcpy(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;
	int k = 0,l = 0;
	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);
		set(wnd_main,MUIA_Window_Sleep,TRUE);
		WriteWindow::sleepAll(TRUE);
		setGdataQuiet(TRUE);
		set(NLIST_messagelistdata,MUIA_NList_Quiet,TRUE);
		set(LISTTREE_messagelistdata,MUIA_NListtree_Quiet,TRUE);
		clearThreadView();
	}

	if(close)
		ViewWindow::checkDeleted(gdata->ID,mdata->ID);
	// check search window
	int entries = 0;
	get(NLIST_search_RES,MUIA_NList_Entries,&entries);
	//printf("%d %d\n",gdata->ID,mdata->ID);
	for(int i=0;i<entries;i++) {
		MessageListData *mdata2 = NULL;
		DoMethod(NLIST_search_RES,MUIM_NList_GetEntry,i,&mdata2);
		//printf("%d %d\n",mdata2->flags[6],mdata2->ID);
		if(mdata->ID == mdata2->ID && gdata->ID == mdata2->flags[6]) {
			//printf("!%d\n",i);
			DoMethod(NLIST_search_RES,MUIM_NList_Remove,i);
			DoMethod(NLIST_search_RES,MUIM_NList_Redraw,MUIV_NList_Redraw_All);
			break;
		}
	}

	delete_file(gdata,mdata);
	if(visible)
		set_and_read(gdata,FALSE);
	set_mdata(mdata,TRUE);
	DoMethod(NLIST_messagelistdata,MUIM_NList_Remove,MUIV_NList_Remove_Active);
	if(visible)
		setEnabled();
	gdata->nummess--;
	if(mdata->flags[1])
		gdata->num_unread--;
	gdata->flags[1]=TRUE;
	if(visible) {
		setGdataActive(k);
		gdata_readID=gdatatemp->ID;
		redrawGdataAll();
		setMdataActive(l);
		write_index(0);
		setGdataQuiet(FALSE);
		threadView();
		set(NLIST_messagelistdata,MUIA_NList_Quiet,FALSE);
		set(LISTTREE_messagelistdata,MUIA_NListtree_Quiet,FALSE);
		set(wnd_main,MUIA_Window_Sleep,FALSE);
		WriteWindow::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!
	//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);
	if(visible)
		WriteWindow::sleepAll(TRUE);

	GroupData * gdatatemp=NULL;
	char buffer[256]="";
	char buffer2[256]="";
	char command[512]="";
	int l = 0;
	getGdataDisplayed(&gdatatemp);
	getMdataActivePos(&l);
	/*if(gdata->ID==-1)
		sprintf(buffer,"NewsCoasterData:outgoing/news_%d",mdata->ID);
	else if(gdata->ID==-2)
		sprintf(buffer,"NewsCoasterData:sent/news_%d",mdata->ID);
	else if(gdata->ID==-3)
		sprintf(buffer,"NewsCoasterData:deleted/news_%d",mdata->ID);
	else if(gdata->ID>=0)
		sprintf(buffer,"NewsCoasterData:folder_%d/news_%d",gdata->ID,mdata->ID);*/
	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[256] = "";
		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++;
			/*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);
		}
	}
	int nmID = gdata2->nextmID;
	if(type == 0) {
		// check search window
		int entries = 0;
		get(NLIST_search_RES,MUIA_NList_Entries,&entries);
		//printf("%d %d\n",gdata->ID,mdata->ID);
		for(int i=0;i<entries;i++) {
			MessageListData *mdata2 = NULL;
			DoMethod(NLIST_search_RES,MUIM_NList_GetEntry,i,&mdata2);
			//printf("%d %d\n",mdata2->flags[6],mdata2->ID);
			if(mdata->ID == mdata2->ID && gdata->ID == mdata2->flags[6]) {
				//printf("!%d\n",i);
				mdata2->ID = nmID;
				mdata2->flags[6] = gdata2->ID;
				/*DoMethod(NLIST_search_RES,MUIM_NList_Remove,i);
				DoMethod(NLIST_search_RES,MUIM_NList_Redraw,MUIV_NList_Redraw_All);*/
				break;
			}
		}
	}

	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);
		if(type==0)
			clearThreadView();
	}
	if(type==0)
	{
		if(gdatatemp->ID!=gdata->ID)
			set_and_read(gdata,FALSE);
		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,FALSE);
			}
		}
	}
	if(visible) {
		set(wnd_main,MUIA_Window_Sleep,FALSE);
		WriteWindow::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!
	// 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[256]="";
	char buffer2[256]="";
	char command[512]="";
	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);
	
	// 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
			for(int 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;
				}
			}
		}

		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,FALSE);
		threadView();
		setEnabled();
		write_index(0);
		if(gdatatemp->ID!=gdata->ID)
			set_and_read(gdatatemp,FALSE);
	}
	//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[MAXFILENAME]="";
	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);
				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 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;
			if( (gdata->ID != gdata2->ID) || m==1) { // copying to the same folder should be allowed!
				set(NLIST_messagelistdata,MUIA_NList_Quiet,TRUE);
				set(LISTTREE_messagelistdata,MUIA_NListtree_Quiet,TRUE);
				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(app,"");
				set(wnd_main,MUIA_Window_Sleep,TRUE);
				WriteWindow::sleepAll(TRUE);
				if(l>0) {
					if(m==0) {
						//clearThreadView();
						statusWindow.setText("Moving..");
					}
					else
						statusWindow.setText("Copying..");
					move_n(gdata,gdata2,mdatalist,l,m,&statusWindow);
				}
				set(wnd_main,MUIA_Window_Sleep,FALSE);
				WriteWindow::sleepAll(FALSE);
			}
			if(mdatalist) {
				delete [] mdatalist;
				mdatalist=NULL;
			}
			set(NLIST_messagelistdata,MUIA_NList_Quiet,FALSE);
			set(LISTTREE_messagelistdata,MUIA_NListtree_Quiet,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;
			getGdataDisplayed(&gdata);
			if(movedel)
            get_gdata(&gdata2,-3);
 			get(NLIST_messagelistdata,MUIA_NList_Entries,&entries);
			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)
				{
					set(NLIST_messagelistdata,MUIA_NList_Quiet,TRUE);
					set(LISTTREE_messagelistdata,MUIA_NListtree_Quiet,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)
					{
						//clearThreadView();
						StatusWindow statusWindow(app,"Deleting..");
						statusWindow.setText("Deleting..");
						set(wnd_main,MUIA_Window_Sleep,TRUE);
						WriteWindow::sleepAll(TRUE);
						/*index_handler * ih=NULL;
						if(gdata2)
							ih = new index_handler(gdata2);
						for(k=0;k<l;k++)
						{
							if(statusWindow.isAborted()==FALSE && running==TRUE)
							{
								//DoMethod(app,MUIM_Application_InputBuffered);
								do_input();
								if(movedel)
								{
									move(gdata,gdata2,&mdatalist[k],0,FALSE,TRUE);
									if(ih)
										ih->write(&mdatalist[k]);
									gdata2->nummess++;
									if(mdatalist[k].flags[1])
										gdata2->num_unread++;
								}
								else
									delete_mess(gdata,&mdatalist[k],FALSE);
							}
							else
								break;
								//delete mdatalist[k];
						}
						if(ih)
							delete ih;*/
						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!
						}
						set(wnd_main,MUIA_Window_Sleep,FALSE);
						WriteWindow::sleepAll(FALSE);
						/*write_index(0);
						threadView();
						setEnabled();
						redrawGdataAll();
						account.save_data(); // update group info on disk!*/
					}
					if(mdatalist) {
						//FreeVec(mdatalist);
						delete [] mdatalist;
						mdatalist=NULL;
					}
					set(NLIST_messagelistdata,MUIA_NList_Quiet,FALSE);
					set(LISTTREE_messagelistdata,MUIA_NListtree_Quiet,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;
   get_gdata(&gdata,-3);
	get(NLIST_messagelistdata,MUIA_NList_Entries,&entries);
	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) {
			set(NLIST_messagelistdata,MUIA_NList_Quiet,TRUE);
			set(LISTTREE_messagelistdata,MUIA_NListtree_Quiet,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(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);
				}
				set(wnd_main,MUIA_Window_Sleep,FALSE);
				WriteWindow::sleepAll(FALSE);
				write_index(0);
				threadView();
				setEnabled();
				redrawGdataAll();
			}
			if(mdatalist) {
				delete [] mdatalist;
				mdatalist=NULL;
			}
			set(NLIST_messagelistdata,MUIA_NList_Quiet,FALSE);
			set(LISTTREE_messagelistdata,MUIA_NListtree_Quiet,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);
	/*if(gdata->ID==-1)
		sprintf(buffer,"copy NewsCoaster:default.index NewsCoasterData:outgoing/.index");
	else if(gdata->ID==-2)
		sprintf(buffer,"copy NewsCoaster:default.index NewsCoasterData:sent/.index");
	else if(gdata->ID==-3)
		sprintf(buffer,"copy NewsCoaster:default.index NewsCoasterData:deleted/.index");
	else if(gdata->ID>=0)
		sprintf(buffer,"copy NewsCoaster:default.index NewsCoasterData:folder_%d/.index",gdata->ID);
	Execute(buffer,NULL,NULL);
	*/
	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(FALSE);
}


void deleteFolderContents() {
	nLog("deleteFolderContents() called\n");
	GroupData * gdata = NULL;
	/*clearThreadView();
	DoMethod(NLIST_messagelistdata,MUIM_NList_Clear);
	write_index(0);
	threadView();
	setEnabled();*/
	//DoMethod(NLIST_groupdata,MUIM_NList_GetEntry,MUIV_NList_GetEntry_Active,&gdata);
	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(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;;
	int result = 0;
	int val=0,val2=0,k=0,l=0;
	char buffer[300]="";
	char buffer2[300]="";
	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 {
				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) {
				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(buffer,"\33cAre you sure you wish to download\nthe Groups list for %s?\n(It may take some time)",server->nntp);
					result=MUI_RequestA(app,0,0,"Get Group List","_Yes|_Cancel",buffer,0);
					if(result==1) {
						result=getgrouplist(server);
						if(result!=-1) {
							get(wnd_groupman,MUIA_Window_Open,&val);
							if(val==FALSE) {
								sprintf(buffer,"\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",buffer,0);
							}
						}
					}
				}
			}
			break;
		}
		case MEN_GETNEWGROUPSDEF:
		case ACC_GETNEWGROUPS:
		{
			Server *server = NULL;
			if(returnID == ACC_GETNEWGROUPS) {
				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 {
					result=getnewgroups(server);
				}
			}
			break;
		}
		case MEN_DISCONNECT:
			closeSockets();
			break;
		case MEN_USER:
			if(registered) {
				sprintf(buffer,"\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",buffer,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:
			get(app,MUIA_Application_ForceQuit,&val);
			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();
				for(int i=0;i<size;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)?!
					if(MUI_RequestA(app,ww->wnd,0,"Save Message","_Save|_Discard","\33cDo you wish to save the changes\nto this message?",0) == 1)
						ww->save();
				}
				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);
			}
			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(buffer,getGMTOffset(),account.bst,gdata->lastdlds);
					set(TXT_eng_LASTDL,MUIA_Text_Contents,buffer);
					if(gdata->ID==-1)
						strcpy(buffer,"outgoing/");
					else if(gdata->ID==-2)
						strcpy(buffer,"sent/");
					else if(gdata->ID==-3)
						strcpy(buffer,"deleted/");
					else
						sprintf(buffer,"folder_%d/",gdata->ID);
					set(TXT_eng_FOLDER,MUIA_Text_Contents,buffer);
					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);
					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) {
					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(buffer,"%s.mbx",gdata->name);
					sleepAll(TRUE);
					BOOL ok = LoadASL(buffer2,"File to save archive as...",buffer,"#?",FALSE);
					sleepAll(FALSE);
					if(ok)
						archiveGroup(gdata,buffer2);
				}
			}
			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:
			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++) {
				getGdata(k,(GroupData **)&ptr);
				if(ptr==NULL)
					continue;
				// make a copy!
				ptr2=new char[256];
				strcpy((char *)ptr2,((GroupData *)ptr)->name);
				DoMethod(NLIST_search_NG,MUIM_NList_InsertSingle,(GroupData *)ptr2,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++) {
				getGdata(k,(GroupData **)&ptr);
				if(ptr==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);
			}
			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) {
				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:
			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_GETGROUPS) {
				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) {
				get(wnd_groupman,MUIA_Window_Open,&yesno);
				if(!yesno) {
					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 {
				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
				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 {
				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) {
				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
			}
			break;
		case MEN_VIEWMESSAGESTREE:
			if(account.mdata_view!=1 && nlisttree==TRUE) {
				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
			}
			break;
		case MEN_READ:
			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)
			{*/
				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)
			{*/
				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)
			{
				getMdataActivePos(&result);
				if(result!=MUIV_NList_Active_Off) {
					getGdataDisplayed(&gdata);
					if(gdata->ID==-2) {
						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:
			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:
			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);
				set(NLIST_messagelistdata,MUIA_NList_Quiet,TRUE);
				set(LISTTREE_messagelistdata,MUIA_NListtree_Quiet,TRUE);
				set(wnd_main,MUIA_Window_Sleep,TRUE);
				MessageListData ** mdatalist = new MessageListData *[entries];
				l=0;
				for(k=0;k<entries;k++) {
					getMdataVisible(k,&mdata);
					if(!mdata->flags[1]) {
							mdatalist[l] = new MessageListData();
							*mdatalist[l++]=*mdata;
					}
				}
				if(l>0) {
					for(k=0;k<l;k++) {
						delete_mess(gdata,mdatalist[k],FALSE);
					}
				}
				if(mdatalist) {
					delete [] mdatalist;
					mdatalist=NULL;
				}
				setEnabled();
				set(wnd_main,MUIA_Window_Sleep,FALSE);
				set(NLIST_messagelistdata,MUIA_NList_Quiet,FALSE);
				set(LISTTREE_messagelistdata,MUIA_NListtree_Quiet,FALSE);
			}
			break;
		case MEN_PDONLINE:
			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);
				set(NLIST_messagelistdata,MUIA_NList_Quiet,TRUE);
				set(LISTTREE_messagelistdata,MUIA_NListtree_Quiet,TRUE);
				set(wnd_main,MUIA_Window_Sleep,TRUE);
				MessageListData ** mdatalist = new MessageListData *[entries];
				l=0;
				for(k=0;k<entries;k++) {
					getMdataVisible(k,&mdata);
					if(mdata->flags[12]) {
							mdatalist[l] = new MessageListData();
							*mdatalist[l++]=*mdata;
					}
				}
				if(l>0) {
					for(k=0;k<l;k++)
						delete_mess(gdata,mdatalist[k],FALSE);
				}
				if(mdatalist) {
					delete [] mdatalist;
					mdatalist=NULL;
				}
				setEnabled();
				set(wnd_main,MUIA_Window_Sleep,FALSE);
				set(NLIST_messagelistdata,MUIA_NList_Quiet,FALSE);
				set(LISTTREE_messagelistdata,MUIA_NListtree_Quiet,FALSE);
			}
			break;
		case MEN_PDALL:
			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);
				set(NLIST_messagelistdata,MUIA_NList_Quiet,TRUE);
				set(LISTTREE_messagelistdata,MUIA_NListtree_Quiet,TRUE);
				deleteFolderContents();
				redrawGdataAll();
				set(NLIST_messagelistdata,MUIA_NList_Quiet,FALSE);
				set(LISTTREE_messagelistdata,MUIA_NListtree_Quiet,FALSE);
				set(wnd_main,MUIA_Window_Sleep,FALSE);
			}
			break;
		case MEN_PDALLALL:
			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(buffer,gdata->name);
					set(ww->STR_write_NG,MUIA_String_Contents,buffer);
					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,buffer);
				set(ww->STR_write_FROM,MUIA_String_Contents,buffer);
				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(buffer,"-- \n");
					DoMethod(ww->ED_write_MESS,MUIM_TextEditor_InsertText,buffer,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);
			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);
			getMdataActivePos(&result);
			if(result!=MUIV_NList_Active_Off) {
				getMdataActive(&mdata);
				set(wnd_main,MUIA_Window_Sleep,TRUE);
				char filename[256] = "";
				char newfilename[256] = "";
				char line[MAXLINE] = "";
				getFilePath(filename,gdata->ID,mdata->ID);
				sprintf(newfilename,"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(newfilename,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\"",newfilename);
					else {
						sprintf(buffer,"run >NIL: %s",account.defviewer);
						sprintf(command,buffer,newfilename);
					}
					for(int k=0;k<account.mimeprefsno;k++) {
						if(strstr("text/plain",account.mimeprefs[k]->type)!=NULL) {
							sprintf(buffer,"run >NIL: %s",account.mimeprefs[k]->viewer);
							sprintf(command,buffer,newfilename);
						}
					}
					Execute(command,NULL,NULL);
				}
			}
			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);
			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);
			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);
				getGdataDisplayed(&gdata);
				sleepAll(TRUE);
				int max = 0;
				for(k=0;k<entries;k++) {
					if(isMdataSelected(k)) {
						getMdataVisible(k,&mdata);
						if(mdata->flags[12]==TRUE)
							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");
					for(k=0;k<ndel;k++) {
						// delete message
						delete_mess(gdata,mdataptr[k],FALSE);
					}
					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);
			getMdataActivePos(&result);
			if(result!=MUIV_NList_Active_Off) {
				MessageListData * mdata2=NULL;
				getMdataActive(&mdata);
				for(k=0;k<entries;k++) {
					getMdataVisible(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);
			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(k=0;k<entries;k++) {
					getMdataVisible(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: {
			get(NLIST_messagelistdata,MUIA_NList_Entries,&entries);
			MessageListData * mdata=NULL;
			for(k=0;k<entries;k++) {
				getMdataVisible(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);
			if(entries>0) {
				getGdataDisplayed(&gdata);
				if(gdata->ID>=0) {
					set(NLIST_messagelistdata,MUIA_NList_Quiet,TRUE);
					set(LISTTREE_messagelistdata,MUIA_NListtree_Quiet,TRUE);
					set(app,MUIA_Application_Sleep,TRUE);
					MessageListData **mdataptr = new MessageListData *[entries];
					int count = 0;
					for(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;
								}
							}
							//write_index_update(gdata,mdata);
							redrawMdata(k);
						}
					}
					//gdata->flags[1]=TRUE;
					write_index_update_multi(gdata,mdataptr,count);
					delete [] mdataptr;
					if(returnID==MEN_MARKUNREAD)
						gdata->num_unread += count;
					else
						gdata->num_unread -= count;
					set(NLIST_messagelistdata,MUIA_NList_Quiet,FALSE);
					set(LISTTREE_messagelistdata,MUIA_NListtree_Quiet,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);
			if(entries>0) {
				getGdataDisplayed(&gdata);
				if(gdata->ID==-1 || (returnID!=MEN_MARKHELD && returnID!=MEN_MARKQUEUED)) {
					set(NLIST_messagelistdata,MUIA_NList_Quiet,TRUE);
					set(LISTTREE_messagelistdata,MUIA_NListtree_Quiet,TRUE);
					set(app,MUIA_Application_Sleep,TRUE);
					MessageListData **mdataptr = new MessageListData *[entries];
					int count = 0;
					for(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;
								}
							}
							//write_index_update(gdata,mdata);
							redrawMdata(k);
						}
					}
					//gdata->flags[1]=TRUE;
					write_index_update_multi(gdata,mdataptr,count);
					delete [] mdataptr;
					set(NLIST_messagelistdata,MUIA_NList_Quiet,FALSE);
					set(LISTTREE_messagelistdata,MUIA_NListtree_Quiet,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);
			if(entries>0) {
				getGdataDisplayed(&gdata);
				if(gdata->ID==-1) {
					set(NLIST_messagelistdata,MUIA_NList_Quiet,TRUE);
					set(LISTTREE_messagelistdata,MUIA_NListtree_Quiet,TRUE);
					set(app,MUIA_Application_Sleep,TRUE);
					char date[256] = "";
					for(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(date,getGMTOffset(),account.bst);
							DateHandler::read_date(&mdata->ds,date,mdata->c_date,mdata->c_time);
							mdata->datec[0] = '\0';
							changedate(gdata,mdata);
							redrawMdata(k);
						}
					}
					set(NLIST_messagelistdata,MUIA_NList_Quiet,FALSE);
					set(LISTTREE_messagelistdata,MUIA_NListtree_Quiet,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);
				if(entries>0) {
					getGdataDisplayed(&gdata);
					set(NLIST_messagelistdata,MUIA_NList_Quiet,TRUE);
					set(LISTTREE_messagelistdata,MUIA_NListtree_Quiet,TRUE);
					set(app,MUIA_Application_Sleep,TRUE);

					int count = 0;
					for(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)
									set(STR_joinmsgs_SUBJECT,MUIA_String_Contents,mdata->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++;
							}
						}
					}

					set(NLIST_messagelistdata,MUIA_NList_Quiet,FALSE);
					set(LISTTREE_messagelistdata,MUIA_NListtree_Quiet,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(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:
			get(NLIST_users_LIST,MUIA_NList_Active,&val);
			if(val!=MUIV_NList_Active_Off)
			{
				User * user;
				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
				{
				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(buffer,user->dataLocation);
					if(result!=0)
					{
						// delete prefs
						/*sprintf(command,"list \"%s\"",buffer);
						Execute(command,NULL,NULL);*/
						sprintf(command,"delete \"%s.prefs\" >NIL:",buffer);
						Execute(command,NULL,NULL);
						sprintf(command,"delete \"%s.killfile\" >NIL:",buffer);
						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(buffer,getstr(STR_newuser_USER));
			if(strlen(buffer)<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;
			}
			char drawer[300];
			correctDrawer(drawer,getstr(STR_newuser_DATALOC));
			val=checkUniqueUser(getstr(STR_newuser_USER),drawer);
			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(buffer,getstr(STR_newuser_PASS));
			if(val==TRUE && strlen(buffer)<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(drawer)==FALSE)
			{
				sprintf(buffer,"\33cError! Couldn't create folder:\n%s",getstr(STR_newuser_DATALOC));
				MUI_RequestA(app,0,0,"New User","_Okay",buffer,0);
				break;
			}
			set(wnd_newuser,MUIA_Window_Open,FALSE);
			User * user;
			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,drawer);
			get(CM_newuser_SUP,MUIA_Selected,&val);
			user->setSupervisor(val);
			addUser(user);
			// copy prefs?
			get(CM_newuser_COPYPREFS,MUIA_Selected,&val);
			if(val) {
				sprintf(buffer,"%s.prefs",user->dataLocation);
				account.save_tofile(buffer);
				sprintf(buffer,"%s.servers",user->dataLocation);
				save_servers(buffer);
			}
			// 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(buffer,"Please enter a new password,\nor press cancel to leave it unchanged.");
				set(TXT_cpwd_INFO,MUIA_String_Contents,buffer);*/
			}
			set(wnd_cpwd,MUIA_Window_Open,TRUE);
			break;
		case CPWD_OKAY:
		{	
			set(wnd_cpwd,MUIA_Window_Open,FALSE);
			get(CM_cpwd_PASS,MUIA_Selected,&val);
			strcpy(buffer,getstr(STR_cpwd_PASS));
			if(val==TRUE && strlen(buffer) < 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(buffer);
			else
				currentUser->setPassword(NULL);
			replaceUser(currentUser);
			loadUsers();
			break;
		}
		case MEN_MUIPREFS:
			DoMethod(app,MUIM_Application_OpenConfigWindow,0);
			break;
		case NG_CHANGED:
			//printf("old_gdata->ID = %d\n",old_gdata->ID);
			if(old_gdata) {
				//printf("old_gdata->flags[1] = %d\n",old_gdata->flags[1]);
				if(old_gdata->flags[1])
					write_index(1,TRUE);
			}
			getGdataActive(&gdata);
			if(gdata!=NULL) {
				v_gdata=gdata;
				if(gdata->ID != gdata_readID) {
					read_index(TRUE);
					//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:
		{
			get(NLIST_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);
			}
			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(buffer,"NewsCoasterData:Folder_%d",nextID);
				if(exists(buffer))
					nextID++;
				else
					break;
			}
			lock=CreateDir(buffer);
			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(buffer,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
				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]);
				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,"");
			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(buffer,ng_edit->ID);
			char comment[81] = "";
			strncpy(comment,*ng_edit->desc=='\0' ? ng_edit->name : ng_edit->desc,80);
			comment[80] = '\0';
			SetComment(buffer,comment);

			get(CY_eng_DEFSIG,MUIA_Cycle_Active,&ng_edit->defsig);
			ng_edit->defsig--;
			get(CM_eng_S,MUIA_Selected,&ng_edit->s);
			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);
			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;
			}
			Server *newsv = getServer(ng_editadv->serverID);
			if(oldsv->ID != newsv->ID) { // reset article pointer?
				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);
			}
			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);
				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[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(mdata->date,getGMTOffset(),account.bst);
					//DateHandler::read_date(&mdata->ds,mdata->date,mdata->c_date,mdata->c_time);
					//r = sprintf(hptr,"Date: %s\n",mdata->date); hptr += r;
					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;

					strcpy(mdata->type,"text/plain");
					r = sprintf(hptr,"Content-Type: %s;\n",mdata->type); hptr += r;

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

					char filename[MAXFILENAME]="";
					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,gdata->ID,this_mdata->ID);
							nLog("%d : %d : %s\n",i,this_mdata->ID,filename2);
							BPTR this_lock = Lock(filename2,ACCESS_READ);
							char buffer[MAXLINE+1] = "";
							BPTR this_file = Open(filename2,MODE_OLDFILE);
							BOOL header = TRUE;
							BOOL body = FALSE;
							int n_nl = 0;
							if(this_file != NULL) {
								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;

						/*GroupData * gdata2 = NULL;
						getGdataDisplayed(&gdata2);*/
						//if(gdata2->ID==-1) // we need to write back index anyway (changed 'READ' flags), so..
						//	write_index(0);
						write_index_single(gdata,mdata);
						//printf("subject: %s\n",mdata->subject);
						//printf("     ID %d\n",mdata->ID);
						gdata->nummess++;
						/*if(gdata2->ID==gdata->ID)
							read_index(TRUE);*/
						redrawGdataAll();
					}
					set(app,MUIA_Application_Sleep,FALSE);
				}
			}
			// no break
		}
		case JOINMSGS_CANCEL:
			set(wnd_joinmsgs,MUIA_Window_Open,FALSE);
			break;
		case ACC_PAGESIG:
			if(accountpage==FALSE) {
				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(buffer,getstr(STR_acc_EMAIL));
			if(strchr(buffer,'@')==NULL || (strchr(buffer,'@')==&buffer[strlen(buffer)-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(buffer,getstr(STR_acc_REALEMAIL));
			if( (strchr(buffer,'@')==NULL || (strchr(buffer,'@')==&buffer[strlen(buffer)-1])) && *buffer!=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;

			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(buffer,getstr(STR_acc_LINELENGTH));
			account.linelength = atoi(buffer);
			if(account.linelength<4)
				account.linelength=4;
			if(account.linelength<60 || account.linelength>80) {
				sprintf(buffer,"\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",buffer,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(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(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));
			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_NNTPCHANGED:
			result=MUI_RequestA(app,0,0,"Reset Article Pointers","_Reset|_Don't Reset","\33cIf you have changed your NNTP server, you should\nreset the article pointers for all newsgroups\n(see documentation for details).",0);
			if(result==1)
				resetArticlePointers();
			break;*/
		case ACC_ADDSERVER:
			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:
			get(wnd_servers,MUIA_Window_Open,&val);
			if(val==FALSE && editServer==NULL) {
				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);
			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->def=TRUE;
					else
						server->def=FALSE;
				}
				DoMethod(NLIST_acc_SERVERS,MUIM_NList_Redraw,MUIV_NList_Redraw_All);
				// update article pointers for all default groups
				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);
				if(result==1) {
					getGdataEntries(&entries);
					for(int i=0;i<entries;i++) {
						getGdata(i,&gdata);
						if(gdata!=NULL) {
							if(gdata->serverID==0) {
								resetArticlePointers(gdata);
								//printf("Reset for group: %s (%d)\n",gdata->name,gdata->serverID);
							}
						}
					}
				}
			}
			break;
		case ACC_MAKEPOSTSERVER:
			get(NLIST_acc_SERVERS,MUIA_NList_Entries,&entries);
			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:
			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) {
						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);
							for(int i=0;i<entries;i++) {
								getGdata(i,&gdata);
								if(gdata!=NULL) {
									if( reset==1 && ( (gdata->serverID==0 && def==TRUE) || gdata->serverID==server->ID ) ) {
										resetArticlePointers(gdata);
										//printf("Reset for group: %s (%d)\n",gdata->name,gdata->serverID);
									}
									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) {
				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);
				if(result==1) {
					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 ) {
								resetArticlePointers(gdata);
								//printf("Reset for group: %s (%d)\n",gdata->name,gdata->serverID);
							}
						}
					}
				}
			}
			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)
			{
				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(buffer,"Select File to Read in","","#?",FALSE);
			sleepAll(FALSE);
			if(ok)
				readInText(ED_acc_SIG,buffer);
			break;
		}
		case ACC_STRKILL:
		case ACC_STRKILLTEMP:
			ptr=(KillFile *)new KillFile();
			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(buffer,getstr(STR_acc_EXPIREKILL));
					((KillFile *)ptr)->expire = atoi(buffer);
					account.defexpiretype=((KillFile *)ptr)->expiretype;
					account.defexpire=((KillFile *)ptr)->expire;

					/*get(CY_acc_TYPEKILL,MUIA_Cycle_Active,&val2);
					((KillFile *)ptr)->type = val2;*/
					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:
			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(buffer,"%d",((KillFile *)ptr)->expire);
				set(STR_acc_EXPIREKILL,MUIA_String_Contents,buffer);
				//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:
			get(NLIST_acc_KILLFILE,MUIA_NList_Active,&val);
			if(val!=MUIV_NList_Active_Off)
			{
				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:
			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:
			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(buffer,temp);
			set(STR_nng_NAME,MUIA_String_Contents,buffer);
			set(wnd_newnewsgroup,MUIA_Window_Open,TRUE);
			set(wnd_newnewsgroup,MUIA_Window_ActiveObject,STR_nng_NAME);
			break;
		case GROUPMAN_FIND:
			get(NLIST_groupman,MUIA_NList_Entries,&val);
			get(NLIST_groupman,MUIA_NList_Active,&val2);
			strcpy(buffer,getstr(STR_groupman_FIND));
			yesno=FALSE;
			if(val>0 && val2>=0 && val2+1<val) {
				for(k=val2+1;k<val;k++) {
					DoMethod(NLIST_groupman,MUIM_NList_GetEntry,k,&temp);
					if(strstr(temp,buffer)) {
						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) {
				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);
				/*set(wnd_main,MUIA_Window_Sleep,TRUE);
				WriteWindow::sleepAll(TRUE);
				set(wnd_search,MUIA_Window_Sleep,TRUE);*/
				sleepAll(TRUE);
				StatusWindow statusWindow(app,"Searching..");
				for(int k=0;k<entries;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,&ptr);
						get_gdata(&gdata,(char *)ptr);
						if(gdata) {
							sprintf(buffer,"Searching: %s",gdata->name);
							char *bufptr = &buffer[ strlen(buffer) ];
							statusWindow.setText(buffer);
							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)
										break;
									sprintf(bufptr," ( %d / %d )",l,entries2);
									statusWindow.setText(buffer);
								}
								mdata = mdataptr[l];
								BOOL found=FALSE;
								if(where < SEARCH_HEADER) { // quick version
									if(casesens) {
										switch(where) {
											case SEARCH_FROM:
												if( strstr(mdata->from,what) )
													found=TRUE;
												break;
											case SEARCH_NEWSGROUPS:
												if( strstr(mdata->newsgroups,what) )
													found=TRUE;
												break;
											case SEARCH_SUBJECT:
												if( strstr(mdata->subject,what) )
													found=TRUE;
												break;
											//case 3:
											//	if( strstr(mdata->date,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:
												if( stristr_q(mdata->newsgroups,what) )
													found=TRUE;
												break;
											case SEARCH_SUBJECT:
												if( stristr_q(mdata->subject,what) )
													found=TRUE;
												break;
											//case 3:
											//	if( stristr_q(mdata->date,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);
			}
			}
			break;
		case SEARCH_MESSAGE:
			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:
		{
			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) {
				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(app,"Scanning..");
				for(int k=0;k<entries;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,&ptr);
						get_gdata(&gdata,(char *)ptr);
						if(gdata) {
							char * cmp = NULL;
							NewMessage newmessageTemp;
							char unknown[] = "Unknown";
							char buffer[256]="";
							sprintf(buffer,"Scanning: %s",gdata->name);
							char *bufptr = &buffer[ strlen(buffer) ];
							statusWindow.setText(buffer);
							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)
										break;
									sprintf(bufptr," ( %d / %d )",l,entries2);
									statusWindow.setText(buffer);
								}
								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);
			}
			}
			break;
		}
		case STATS_SORT:
			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);
}

/*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;
}

/*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;
}

/*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[256];
	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[256];
	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 {
			*array++ = msg->TreeNode->tn_Name;
			*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[256];
	static char buf1[256];
	static char buf2[256];
	static char buf3[256];
	static char buf4[256];
	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 {
		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[256];
	static char buf1[256];
	static char buf2[256];
	static char buf3[256];
	static char buf4[256];
	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[256];
	static char buf1[256];
	static char buf2[256];
	static char buf3[256];
	static char buf4[256];
	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--;
		
		/*
		*array++ = " ";
		*array++ = "\33bSubject";
		*array++ = "\33bDate";
		*array++ = "\33bFrom";
		*array++ = "\33bSize";
		*array = "\33bLines";*/
	}
	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[256];
	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[256];
	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[256],buf2[256],buf3[256];
	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);
}

/*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(app,"Importing Folder..");
					import_folder(word2,&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;
					strcpy(tempNM.getThisHeader,word2);
					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) {
				getMdataActive(&mdata);
				//if(*mdata->datec == '\0')
				//	sprintf(mdata->datec,"%s %s",mdata->c_date,mdata->c_time);
				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);
				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,TRUE);
				}
			}
			else if(stricmp(word1,"SETFOLDERBYNAME")==0) { // by ID
				if(*word2 != NULL)
					set_and_read(word2,TRUE);
			}
			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 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_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_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_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_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 };*/

int realmain() {
	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;
	}
	
	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.52",
		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_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, 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,	FALSE,
			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("Logging Enabled?:"), Child, CM_acc_LOGGING = CheckMark(FALSE),
							Child, Label1("Delete Log on Startup?:"), Child, CM_acc_LOGDEL = CheckMark(TRUE),

							Child, Label1("Add Adjustment for DST?:"), Child, CM_acc_BST = CheckMark(FALSE),
							Child, Label1("Switch Groups when d/l?:"), Child, CM_acc_VGROUPDL = CheckMark(FALSE),

							Child, Label1("Use Locale Prefs?:"), Child, CM_acc_USELOCALETZ=CheckMark(FALSE),
							Child, Label1("Don't confirm when deleting?:"), Child, CM_acc_NOCONFIRMDEL = CheckMark(FALSE),

							Child, Label1("Delete header if body not avail.?:"), Child, CM_acc_DELONLINE = CheckMark(TRUE),
							Child, Label1("Always confirm on quit?:"), Child, CM_acc_CONFIRMQUIT = CheckMark(TRUE),

							Child, Label1("Don't show from/subject when d/l?:"), Child, CM_acc_QUIETDL = CheckMark(FALSE),
							Child, Label1("Always check for duplicates?:"), Child, CM_acc_CHECKFORDUPS = CheckMark(FALSE),

							//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_MultiSelect,		MUIV_NList_MultiSelect_Default,
								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_MultiSelect,		MUIV_NList_MultiSelect_Default,
								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_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(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(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)
		MUI_DisposeObject(app);
	nLog("  MUI_DisposeObject() called\n");

	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 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");
		}
	}
	return realmain();
}

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