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

#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 <ctype.h>

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

//static LONG w_cmap[9];

static char *Pages_write[]   = {"Message","Attachments","Options",NULL };

void WriteWindow::save() {
	printf("save!\n");
	WriteWindow *ww = this;
	GroupData *gdata = NULL;
	get_gdata(&gdata,-1);
	MessageListData *mdata = write_message(TRUE,FALSE);
	if(ww->newmessage.edit==FALSE)
		ww->newmessage.sent=FALSE;
	ww->newmessage.edit=TRUE;
	ww->newmessage.reply=FALSE;
	//get_refs(&(ww->newmessage),gdata,mdata);
	get_refs(&(ww->newmessage),gdata,mdata,GETREFS_ALL);
	/*int nrefs = ww->newmessage.nrefs;
	char *temp[MAX_REFS];
	int i=0;
	for(i=0;i<nrefs;i++)
		temp[i] = ww->newmessage.references[i];
	get_refs(&(ww->newmessage),gdata,mdata,GETREFS_NONE);
	ww->newmessage.nrefs = nrefs;
	for(i=0;i<nrefs;i++)
		ww->newmessage.references[i] = temp[i];*/
	printf("last ref: %s\n",ww->newmessage.references[ww->newmessage.nrefs-1]);

	strncpy(ww->newmessage.messageID,mdata->messageID,NEWMESS_short);
	ww->newmessage.messageID[NEWMESS_short] = '\0';
	//delete mdata;
}

ULONG HOOK3( WriteWindow::TextEditor_Dispatcher_write, IClass *, cl, a0, Object *, obj, a2, struct 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(NULL, NULL, 0L, NULL, "Continue", errortxt);
			}
			break;
	}
	return DoSuperMethodA(cl,obj,(Msg)msg);
}

/*SAVEDS VOID ASM WriteWindow::objStrFunc(REG(a2) Object *pop,REG(a1) Object *str) {*/
VOID HOOK2( WriteWindow::objStrFunc, Object *, pop, a2, Object *, str, a1 )

	WriteWindow *ww = NULL;
	// hacky!
	int size=ptrs->getSize();
	WriteWindow ** data = (WriteWindow **)ptrs->getData();
	for(int i=0;i<size;i++) {
		if(data[i]->LIST_write_MIME == pop) {
			ww = data[i];
			break;
		}
	}
	if(ww == NULL) {
		nLog("Error - can't find WriteWindow for PopObject!\n");
		return;
	}
	char *x = NULL;
	DoMethod(pop,MUIM_List_GetEntry,MUIV_List_GetEntry_Active,&x);
	set(str,MUIA_String_Contents,x);
	int entries = 0;
	MIMEType * mime = NULL;
	get(ww->NLIST_write_ATT,MUIA_NList_Entries,&entries);
	if(entries>0) {
		int val = 0;
		get(ww->NLIST_write_ATT,MUIA_NList_Active,&val);
		if(val!=MUIV_NList_Active_Off) {
			DoMethod(ww->NLIST_write_ATT,MUIM_NList_GetEntry,MUIV_NList_GetEntry_Active,&mime);
			strncpy(mime->type,x,MIMETYPE_TYPE_LEN);
			mime->type[MIMETYPE_TYPE_LEN] = '\0';
			DoMethod(ww->NLIST_write_ATT,MUIM_NList_ReplaceSingle,mime,MUIV_NList_Insert_Active,NOWRAP,ALIGN_LEFT);
			DoMethod(ww->NLIST_write_ATT,MUIM_NList_Redraw,MUIV_NList_Redraw_Active);
		}
	}
}

/*LONG ASM WriteWindow::addNGFunc(REG(a0) Hook * hook,REG(a2) Object * object,REG(a1) WriteWindow ** W) {*/
LONG HOOK3( WriteWindow::addNGFunc, Hook *, hook, a0, Object *, object, a2, WriteWindow **, W, a1 )
	WriteWindow * ww = *W;
	if(object == ww->BT_write_NG)
		getNGChoice("Please Select a Newsgroup","Add/Remove Newsgroup",ww->STR_write_NG,FALSE);
	else if(object == ww->BT_write_FU)
		getNGChoice("Please Select a Newsgroup","Add/Remove Newsgroup",ww->STR_write_FOLLOWUP,TRUE);
	return 0;
}

/* A safe way to delete the class from a Hook called with an object
 * belonging to the window. We can't do a 'delete ww' or whatever from
 * within the Hook, since the destructor calls MUI_DisposeObject on the MUI
 * objects associated with the class. Instead, use:
 *     DoMethod(app, MUIM_Application_PushMethod, app, 3, MUIM_CallHook,
 *         &disposeHook, ww );
 */
LONG HOOK3( WriteWindow::disposeFunc, Hook *, hook, a0, Object *, object, a2, WriteWindow **, W, a1 )
	nLog("WriteWindow::disposeFunc() called\n");
	//printf("WriteWindow::disposeFunc() called\n");
	WriteWindow * ww = *W;
	delete ww;
	return 0;
}

/*LONG ASM WriteWindow::completeFunc(REG(a0) Hook * hook,REG(a2) Object * object,REG(a1) WriteWindow ** W) {*/
LONG HOOK3( WriteWindow::completeFunc, Hook *, hook, a0, Object *, object, a2, WriteWindow **, W, a1 )
	WriteWindow * ww = *W;
	/*WriteWindow * ww = (WriteWindow *)p[0];
	int ID = *((int *)p[1]);
	printf("%d\n",ID);*/
	int result;
	BOOL close = FALSE;
	if(object == ww->BT_write_P) {
		if(*getstr(ww->STR_write_SUBJECT)==0) {
			MUI_RequestA(app,0,0,"Write Message","_Okay","You must specify a subject\nfor your message!",0);
			set(ww->wnd,MUIA_Window_ActiveObject,ww->STR_write_SUBJECT);
		}
		else {
			MessageListData *mdata = ww->write_message(FALSE,TRUE);
			//delete mdata;
			set(ww->wnd,MUIA_Window_Open,FALSE);
			close = TRUE;
			DoMethod(ww->ED_write_MESS,MUIM_TextEditor_ClearText);
			postnews(1);
		}
	}
	else if(object == ww->BT_write_PL) {
		if(*getstr(ww->STR_write_SUBJECT)==0)
			MUI_RequestA(app,0,0,"Write Message","_Okay","You must specify a subject\nfor your message!",0);
		else {
			MessageListData *mdata = ww->write_message(FALSE,FALSE);
			//delete mdata;
			set(ww->wnd,MUIA_Window_Open,FALSE);
			close = TRUE;
			DoMethod(ww->ED_write_MESS,MUIM_TextEditor_ClearText);
		}
	}
	else if(object == ww->BT_write_H) {
		if(*getstr(ww->STR_write_SUBJECT)==0)
			MUI_RequestA(app,0,0,"Write Message","_Okay","You must specify a subject\nfor your message!",0);
		else {
			MessageListData *mdata = ww->write_message(TRUE,FALSE);
			//delete mdata;
			set(ww->wnd,MUIA_Window_Open,FALSE);
			close = TRUE;
			DoMethod(ww->ED_write_MESS,MUIM_TextEditor_ClearText);
		}
	}
	else if(object == ww->BT_write_C || object == ww->wnd) {
		result=MUI_RequestA(app,0,0,"Cancel","_Discard|_Cancel","\33cAre you sure you wish\nto discard all changes to this message\n(since last saved)?",0);
		if(result==1) {
			set(ww->wnd,MUIA_Window_Open,FALSE);
			close = TRUE;
			DoMethod(ww->ED_write_MESS,MUIM_TextEditor_ClearText);
			set(ww->STR_write_SUBJECT,MUIA_String_Contents,"");
			for(int k=0;k<ww->newmessage.nrefs;k++) {
				if(ww->newmessage.references[k]) {
					delete ww->newmessage.references[k];
					ww->newmessage.references[k]=NULL;
				}
				ww->newmessage.nrefs=0;
			}
		}
	}
	if(close) {
		//delete ww;
		DoMethod(app, MUIM_Application_PushMethod, app, 3, MUIM_CallHook, &disposeHook, ww );
	}
	return close ? 1 : 0;
}

/*LONG ASM WriteWindow::rot13Func(REG(a0) Hook * hook,REG(a2) Object * object,REG(a1) WriteWindow ** W) {*/
LONG HOOK3( WriteWindow::rot13Func, Hook *, hook, a0, Object *, object, a2, WriteWindow **, W, a1 )
	WriteWindow * ww = *W;
	rot13(ww->ED_write_MESS);
	return 0;
}

/*LONG ASM WriteWindow::readFunc(REG(a0) Hook * hook,REG(a2) Object * object,REG(a1) WriteWindow ** W) {*/
LONG HOOK3( WriteWindow::readFunc, Hook *, hook, a0, Object *, object, a2, WriteWindow **, W, a1 )
	static char buffer[1024] = "";
	WriteWindow * ww = *W;
	if(LoadASL(buffer,"Select File to Read in","","#?",FALSE))
		readInText(ww->ED_write_MESS,buffer);
	return 0;
}

/*LONG ASM WriteWindow::cysigFunc(REG(a0) Hook * hook,REG(a2) Object * object,REG(a1) WriteWindow ** W) {*/
LONG HOOK3( WriteWindow::cysigFunc, Hook *, hook, a0, Object *, object, a2, WriteWindow **, W, a1 )
	//printf("ARSE\n");
	WriteWindow * ww = *W;
	int val = 0;
	char *temp=NULL,*temp2=NULL;
	get(ww->CY_write_SIG,MUIA_Cycle_Active,&val);
	val--;
	set(ww->ED_write_MESS,MUIA_TextEditor_ExportWrap,0);
	temp=(char *)DoMethod(ww->ED_write_MESS,MUIM_TextEditor_ExportText);
	if(temp) {
		temp2=temp;
		for(;;) {
			temp2=strstr(temp2,"-- ");
			if(temp2==NULL)
				break;
			if(temp2==temp)
				break;
			if(temp2[-1]=='\n' && temp2[3]=='\n')
				break;
			temp2++;
		}
		if(temp2) {
			if(temp2[-1]=='\n')
				temp2--;
			*temp2=0;
		}
		DoMethod(ww->ED_write_MESS,MUIM_TextEditor_ClearText);
		DoMethod(ww->ED_write_MESS,MUIM_TextEditor_InsertText,temp,MUIV_TextEditor_InsertText_Bottom);
		if(val>=0) {
			if( sigs[val] && *(sigs[val]) != '\0' ) {
				DoMethod(ww->ED_write_MESS,MUIM_TextEditor_InsertText,"\n-- \n",MUIV_TextEditor_InsertText_Bottom);
				DoMethod(ww->ED_write_MESS,MUIM_TextEditor_InsertText,sigs[val],MUIV_TextEditor_InsertText_Bottom);
			}
		}
		FreeVec(temp); // should be FreeVec
		temp=NULL;
	}
	set(ww->ED_write_MESS,MUIA_TextEditor_ExportWrap,account.linelength);
	return 0;
}

/*LONG ASM WriteWindow::attFunc(REG(a0) Hook * hook,REG(a2) Object * object,REG(a1) WriteWindow ** W) {*/
LONG HOOK3( WriteWindow::attFunc, Hook *, hook, a0, Object *, object, a2, WriteWindow **, W, a1 )
	WriteWindow * ww = *W;
	MIMEType *ptr;
	int val;
	if(object == ww->BT_write_ADDATT) {
		ptr=new MIMEType;
		if(LoadASL(ptr->file,"Please Select File to Attach","","#?",FALSE)) {
			exfile(ptr);
			set(ww->STR_write_MIME,MUIA_String_Contents,ptr->type);
			DoMethod(ww->NLIST_write_ATT,MUIM_NList_InsertSingle,ptr,MUIV_NList_Insert_Bottom);
			set(ww->NLIST_write_ATT,MUIA_NList_Active,MUIV_NList_Active_Bottom);
		}
	}
	else if(object == ww->BT_write_DELATT) {
		set(ww->STR_write_MIME,MUIA_String_Contents,"");
		get(ww->NLIST_write_ATT,MUIA_NList_Active,&val);
		if(val!=MUIV_NList_Active_Off)
			DoMethod(ww->NLIST_write_ATT,MUIM_NList_Remove,val);
	}
	else if(object == ww->NLIST_write_ATT) {
		DoMethod(ww->NLIST_write_ATT,MUIM_NList_GetEntry,MUIV_NList_GetEntry_Active,&ptr);
		if(ptr)
			set(ww->STR_write_MIME,MUIA_String_Contents,ptr->type);
	}
	return 0;
}

/*LONG ASM WriteWindow::menusFunc(REG(a0) Hook * hook,REG(a2) Object * object,REG(a1) APTR * param) {*/
//LONG ASM ViewWindow::menusFunc(REG(a0) Hook * hook,REG(a2) Object * object,REG(a1) ViewWindow ** W,int * uD) {
LONG HOOK3( WriteWindow::menusFunc, Hook *, hook, a0, Object *, object, a2, APTR *, param, a1 )
	WriteWindow * ww = (WriteWindow *)param[0];
	int uD = (int)param[1];
	switch (uD) {
		case WRITE_SAVE:
			ww->save();
			return 0;
	}
	return 0;
}

Hook WriteWindow::addNGHook ={ {NULL,NULL},(HOOKFUNC)&WriteWindow::addNGFunc,NULL,NULL};
Hook WriteWindow::disposeHook ={ {NULL,NULL},(HOOKFUNC)&WriteWindow::disposeFunc,NULL,NULL};
Hook WriteWindow::completeHook ={ {NULL,NULL},(HOOKFUNC)&WriteWindow::completeFunc,NULL,NULL};
Hook WriteWindow::rot13Hook ={ {NULL,NULL},(HOOKFUNC)&WriteWindow::rot13Func,NULL,NULL};
Hook WriteWindow::readHook ={ {NULL,NULL},(HOOKFUNC)&WriteWindow::readFunc,NULL,NULL};
Hook WriteWindow::cysigHook ={ {NULL,NULL},(HOOKFUNC)&WriteWindow::cysigFunc,NULL,NULL};
Hook WriteWindow::attHook ={ {NULL,NULL},(HOOKFUNC)&WriteWindow::attFunc,NULL,NULL};
Hook WriteWindow::objStrHook = { { NULL,NULL },(HOOKFUNC)&WriteWindow::objStrFunc,NULL,NULL };
Hook WriteWindow::menusHook ={ {NULL,NULL},(HOOKFUNC)&WriteWindow::menusFunc,NULL,NULL};
int WriteWindow::count=0;
Vector *WriteWindow::ptrs = new Vector(32);

MUI_CustomClass *WriteWindow::editor_mcc_write = NULL;

WriteWindow::WriteWindow(char *scrtitle) {
	nLog("WriteWindow((char *)%s) constructor called\n",scrtitle);
	this->count++;
	ptrs->add(this);
	if(editor_mcc_write == NULL)
		editor_mcc_write = MUI_CreateCustomClass(NULL, "TextEditor.mcc", NULL, 0, (void *)&WriteWindow::TextEditor_Dispatcher_write);

	NewMenu MenuDataWrite[]= {
		{NM_TITLE,"Message",						0,0,0,	(APTR)MENWRITE_MESSAGE},
		{NM_ITEM,"Save",							"S",0,0,	(APTR)WRITE_SAVE},
		
		{NM_END,NULL,0,0,0,(APTR)0},
	};

	SLD_write_MESS = ScrollbarObject, End;
	{
		wnd = WindowObject,
			MUIA_Window_Title,			"Write",
			MUIA_Window_ID,				MAKE_ID('W','R','T','E') + (count - 1),
			MUIA_Window_ScreenTitle,	scrtitle,
			MUIA_Window_CloseGadget,	TRUE,
			MUIA_Window_Menustrip,		menustrip=MUI_MakeObject(MUIO_MenustripNM,MenuDataWrite,0),
			MUIA_HelpNode,					"WIN_WRITE",
			
			WindowContents, VGroup,
				Child, RegisterGroup(Pages_write),
					MUIA_Register_Frame, TRUE,
					MUIA_CycleChain, 1,
					//page 1
					Child, VGroup,
						Child, ColGroup(2),
							Child, Label2("Newsgroups:"),
							Child, ColGroup(2),
								Child, STR_write_NG=BetterString("",NEWMESS_long+1),
								Child, BT_write_NG=SimpleButton("+/-"),
 								End,
							Child, Label2("To:"), Child, STR_write_TO=BetterString("",NEWMESS_long+1),
							Child, Label2("Subject:"), Child, STR_write_SUBJECT=BetterString("",NEWMESS_long+3),
							End,
						Child, HGroup,
							MUIA_Group_Spacing, 0,
							Child, ED_write_MESS = (Object*)NewObject(editor_mcc_write->mcc_Class, NULL,
								MUIA_TextEditor_Slider,			SLD_write_MESS,
								//MUIA_TextEditor_ColorMap,		w_cmap,
								MUIA_TextEditor_ImportHook,	MUIV_TextEditor_ImportHook_Plain,
								//MUIA_TextEditor_ImportHook,	MUIV_TextEditor_ImportHook_EMail,
								//MUIA_TextEditor_ExportHook,	MUIV_TextEditor_ExportHook_Plain,
								MUIA_TextEditor_ExportHook,	MUIV_TextEditor_ExportHook_EMail,
								MUIA_TextEditor_ExportWrap,	72,
								MUIA_TextEditor_FixedFont,		TRUE,
								MUIA_CycleChain, 1,
								End,
							Child, SLD_write_MESS,
							End,
						End,
					//page 2
					Child, VGroup,
						Child, NListviewObject,
							MUIA_NListview_NList,			NLIST_write_ATT=NListObject,
								MUIA_NList_Title,				TRUE,
								MUIA_NList_DragSortable,	TRUE,
								MUIA_NList_DragType,			MUIV_NList_DragType_Immediate,
								MUIA_NList_DisplayHook,		&DisplayHook_mime,
								MUIA_NList_DestructHook,	&DestructHook_mime,
								MUIA_NList_Format,			",,",
								MUIA_NList_MinColSortable,	0,
								End,
							End,
						Child, ColGroup(3),
							Child, BT_write_ADDATT=SimpleButton("_Add Attachment"),
							Child, BT_write_DELATT=SimpleButton("_Delete Attachment"),
							Child, POP_write_MIME = PopobjectObject,
								MUIA_Popstring_String, STR_write_MIME=BetterString("",32),
								MUIA_Popstring_Button, PopButton(MUII_PopUp),
								MUIA_Popobject_StrObjHook, &StrObjHook,
								MUIA_Popobject_ObjStrHook, &objStrHook,
								MUIA_Popobject_WindowHook, &WindowHook,
								MUIA_Popobject_Object, LIST_write_MIME = ListviewObject,
									MUIA_Listview_List, ListObject,
										InputListFrame,
										MUIA_List_SourceArray, POPA_write_mime,
										End,
									End,
								End,
							End,
						End,
					//page 3
					Child, VGroup,
						Child, ColGroup(2),
							Child, Label2("From:"), Child, STR_write_FROM=BetterString("",256),
						End,
							Child, ColGroup(3),
							Child, Label2("Followup-To:"), Child, STR_write_FOLLOWUP=BetterString("",512),
							Child, BT_write_FU=SimpleButton("+/-"),
							End,
						End,
					End,
				Child, ColGroup(5),
				//Child, ColGroup(4),
					Child, BT_write_P=SimpleButton("_Post"),
					Child, BT_write_PL=SimpleButton("Send to _Queue"),
					Child, BT_write_H=SimpleButton("P_ostpone"),
					Child, BT_write_ROT13=SimpleButton("_Rot13"),
					Child, BT_write_C=SimpleButton("C_ancel"),
					End,
				Child, ColGroup(2),
					Child, BT_write_READ=SimpleButton("Read From _File"),
					Child, CY_write_SIG=Cycle(CYA_nng_sigs),
					End,
				End,
			End;

		DoMethod(app,OM_ADDMEMBER,wnd);
		
		DoMethod(wnd,MUIM_Notify,MUIA_Window_CloseRequest,TRUE,
			BT_write_C,3,MUIM_CallHook,&completeHook,this);

		DoMethod(BT_write_NG,MUIM_Notify,MUIA_Pressed,FALSE,
			MUIV_Notify_Self,3,MUIM_CallHook,&addNGHook,this);
		DoMethod(BT_write_FU,MUIM_Notify,MUIA_Pressed,FALSE,
			MUIV_Notify_Self,3,MUIM_CallHook,&addNGHook,this);

		DoMethod(BT_write_P,MUIM_Notify,MUIA_Pressed,FALSE,
			MUIV_Notify_Self,3,MUIM_CallHook,&completeHook,this);
		DoMethod(BT_write_PL,MUIM_Notify,MUIA_Pressed,FALSE,
			MUIV_Notify_Self,3,MUIM_CallHook,&completeHook,this);
		DoMethod(BT_write_H,MUIM_Notify,MUIA_Pressed,FALSE,
			MUIV_Notify_Self,3,MUIM_CallHook,&completeHook,this);
		DoMethod(BT_write_C,MUIM_Notify,MUIA_Pressed,FALSE,
			MUIV_Notify_Self,3,MUIM_CallHook,&completeHook,this);

		DoMethod(BT_write_ROT13,MUIM_Notify,MUIA_Pressed,FALSE,
			MUIV_Notify_Self,3,MUIM_CallHook,&rot13Hook,this);

		DoMethod(BT_write_READ,MUIM_Notify,MUIA_Pressed,FALSE,
			MUIV_Notify_Self,3,MUIM_CallHook,&readHook,this);

		DoMethod(CY_write_SIG,MUIM_Notify,MUIA_Cycle_Active,MUIV_EveryTime,
			MUIV_Notify_Self,3,MUIM_CallHook,&cysigHook,this);

		DoMethod(BT_write_ADDATT,MUIM_Notify,MUIA_Pressed,FALSE,
			MUIV_Notify_Self,3,MUIM_CallHook,&attHook,this);
		DoMethod(BT_write_DELATT,MUIM_Notify,MUIA_Pressed,FALSE,
			MUIV_Notify_Self,3,MUIM_CallHook,&attHook,this);
		DoMethod(NLIST_write_ATT,MUIM_Notify,MUIA_NList_Active,MUIV_EveryTime,
			MUIV_Notify_Self,3,MUIM_CallHook,&attHook,this);
		DoMethod(LIST_write_MIME,MUIM_Notify,MUIA_Listview_DoubleClick,TRUE,
			POP_write_MIME,2,MUIM_Popstring_Close,TRUE);

		DoMethod(wnd,MUIM_Notify,MUIA_Window_MenuAction,MUIV_EveryTime,
			app,4,MUIM_CallHook,&menusHook,this,MUIV_TriggerValue);
		
		set(BT_write_NG,MUIA_HorizWeight,25);
		set(BT_write_FU,MUIA_HorizWeight,25);

		set(BT_write_P,MUIA_ShortHelp,"Send your message\nimmediately (you must be\nonline) and copy the message\nto the Sent folder");
		set(BT_write_NG,MUIA_ShortHelp,"Add or remove a newsgroup to\npost to by selecting from\nthe list");
		set(BT_write_FU,MUIA_ShortHelp,"Add or remove a newsgroup to\nfollowup-to to by selecting\nfrom the list");
		set(BT_write_PL,MUIA_ShortHelp,"Copy the message to the\nOutgoing folder, to be\nposted later when you are\nonline by selecting the menu\noption 'Project/Send News'");
		set(BT_write_H,MUIA_ShortHelp,"Copy the message to the\nOutgoing folder, but do not\nsend at all (you must\nre-edit it first)");
		set(BT_write_C,MUIA_ShortHelp,"Cancel this message (or\ncancel the changes to it if\nthis is an edited\nmessage)");
		set(BT_write_READ,MUIA_ShortHelp,"Insert text read in from a\nfile");
		set(CY_write_SIG,MUIA_ShortHelp,"Select the .sig you wish to\nuse for this message");
		set(STR_write_TO,MUIA_ShortHelp,"If you wish to email the\nmessage to anyone, place\ntheir email address here.\nMultiple emails must be\nseparated with a comma");
		set(STR_write_NG,MUIA_ShortHelp,"The Newsgroup you wish to\npost to. Multiple Newsgroups\nmust be separated with a\ncomma");
		set(STR_write_SUBJECT,MUIA_ShortHelp,"The subject of your message");
		set(STR_write_FROM,MUIA_ShortHelp,"What you wish to appear in\nthe 'From:' header");
		set(STR_write_FOLLOWUP,MUIA_ShortHelp,"Followups to your message\nwill only go to the\nnewsgroups specified here,\nor they will go to the same\nnewsgroups listed in the\nNewsgroups field, if this\nfield is left blank");
	}

	set(STR_write_TO,MUIA_String_Contents,"");
	set(STR_write_SUBJECT,MUIA_String_Contents,"");
	set(STR_write_FOLLOWUP,MUIA_String_Contents,"");

	set(ED_write_MESS,MUIA_TextEditor_ExportWrap,account.linelength);
	
	/*{
		static char malicious[256] = "";
		malicious[0] = 27;
		s trcpy(&malicious[1],"I[4:APIPE:Echo >CON:////Hacked/AUTO/WAIT/CLOSE/ Owned]");
		//printf("%s\n",malicious);
		set(STR_write_SUBJECT,MUIA_String_Contents,malicious);
	}*/
}

WriteWindow::~WriteWindow() {
	nLog("WriteWindow::~WriteWindow() called - count = %d\n",count);
	set(wnd,MUIA_Window_Open,FALSE);
	DoMethod(ED_write_MESS,MUIM_TextEditor_ClearText);
	DoMethod(app,OM_REMMEMBER,wnd);
	/*nLog("about to dispose of TextEditor Custom Class\n");
	if(editor_mcc_write)
		MUI_DeleteCustomClass(editor_mcc_write);*/
	nLog("about to dispose wnd\n");
	MUI_DisposeObject(wnd);
	this->count--;
	ptrs->removeElement(this);
}

void WriteWindow::sleepAll(BOOL sleep) {
	int size=ptrs->getSize();
	WriteWindow ** data = (WriteWindow **)ptrs->getData();
	for(int i=0;i<size;i++)
		set(data[i]->wnd,MUIA_Window_Sleep,sleep);
}

MessageListData *WriteWindow::write_message(BOOL hold,BOOL online) {
	nLog("WriteWindow::write_message((BOOL)%d,(BOOL)%d) called\n",hold,online);
	//printf("%d:%s\n",newmessage.references[0],newmessage.references[0]);
	WriteWindow *write = this;
	set(write->wnd,MUIA_Window_Sleep,TRUE);
	set(write->ED_write_MESS,MUIA_TextEditor_ExportWrap,0);
	unsigned char * text=(unsigned char *)DoMethod(write->ED_write_MESS,MUIM_TextEditor_ExportText);
	nLog("  Text Exported from TextEditor.mcc\n");
	set(write->ED_write_MESS,MUIA_TextEditor_ExportWrap,account.linelength);
	
	BOOL bit7 = translateCharset(text,account.charset_write);
	unsigned char *src = text; // NB unsigned char
	unsigned char *space = NULL;
	int lnw = 0,eqlength = 20;
	int llength = account.linelength;
	if(*src=='>' || *src=='|' || *src==':' || *src=='!') // assume quoted
		llength += eqlength;
	for(;;) {
		if(isspace(*src))
			space = src;
		if(*src=='\n') {
			src++;
			lnw=0;
			llength = account.linelength;
			if(*src=='>' || *src=='|' || *src==':' || *src=='!') // assume quoted
				llength += eqlength;
		}
		else if(*src==0)
			break;
		else {
			src++;
			lnw++;
		}
		if(lnw>=llength) {
			if(isspace(*src)) {
				*src++='\n';
				lnw=0;
				llength=account.linelength;
				if(*src=='>' || *src=='|' || *src==':' || *src=='!') // assume quoted
					llength+=eqlength;
			}
			else {
				int dist = (int)src - (int)space;
				if(dist <= llength) {
					src = space;
					*src++='\n';
					lnw=0;
					llength=account.linelength;
					if(*src=='>' || *src=='|' || *src==':' || *src=='!') // assume quoted
						llength+=eqlength;
				}
			}
		}
	}
	int textlen = (int)src - (int)text;
	nLog("  Text Wrapped\n");
	MessageListData * mdata = new MessageListData();
	mdata->init();
	mdata->flags[0]=(int)hold;
	mdata->flags[2]=(int)online;
	mdata->flags[6]=-1;
	char buffer[1024] = "";
	char boundary[256] = "";

	// mark message as replied to if this is a reply (or followup)
	if(write->newmessage.reply) {
		GroupData * gdata = NULL;
		get_gdata(&gdata,write->newmessage.replied_gdataID);
		if(gdata!=NULL) {
			//set_and_read(write->newmessage.replied_gdataID,TRUE);
			MessageListData * mdata2 = NULL;
			//get_mdata(&mdata2,write->newmessage.replied_mdataID);
			BOOL del = get_mdata(&mdata2,gdata,write->newmessage.replied_mdataID,TRUE);
			if(mdata2 != NULL) {
				mdata2->flags[10]=TRUE;
				write_index_update(gdata,mdata2,NLIST_messagelistdata);
				if(del)
					delete mdata;
			}
		}
	}
	
	// delete old message if edited
	GroupData * gdata = NULL;
	get_gdata(&gdata,-1);
	if(write->newmessage.edit==TRUE && write->newmessage.sent==FALSE) {
		//set_and_read(-1,TRUE);
		Vector *vector = NULL;
		MessageListData *mdata = NULL;
		GroupData * cdg = NULL;
		getGdataDisplayed(&cdg);
		if(cdg->ID == gdata->ID) {
			int entries = 0;
			get(NLIST_messagelistdata,MUIA_NList_Entries,&entries);
			for(int l=0;l<entries;l++) {
				MessageListData * mdata2 = NULL;
				DoMethod(NLIST_messagelistdata,MUIM_NList_GetEntry,l,&mdata2);
				if(strcmp(mdata2->messageID,write->newmessage.messageID)==0) {
					mdata = mdata2;
					break;
				}
			}
		}
		else {
			// todo: we end up reading in the index twice; once here, and again in write_index_delete !
			vector = new Vector(2048);
			if( read_index(gdata, vector) ) {
				for(int i=0;i<vector->getSize();i++) {
					MessageListData *mdata2 = ((MessageListData **)vector->getData())[i];
					if(strcmp(mdata2->messageID,write->newmessage.messageID)==0) {
						mdata = mdata2;
						break;
					}
				}
			}
		}
		if(mdata != NULL) {
			delete_mess(gdata,mdata,FALSE);
			//threadView();
			setEnabled();
			//write_index(0);
		}
		if(vector != NULL) {
			vector->flush();
			delete vector;
		}
	}
	//printf("%d\n",gdata->nummess);
	//get_index_entries(gdata);

	int multipart = 0;
	get(write->NLIST_write_ATT,MUIA_NList_Entries,&multipart);
	char x_newsreader[256] = "";
	//if(registered)
	{
		if(account.xnews)
			sprintf(x_newsreader,"NewsCoaster (v%s)",version);
		else
			sprintf(x_newsreader,"NewsCoaster (v%s) [Amiga, 68k] by Mark Harman",version);
	}
	/*else {
		if(account.xnews)
			sprintf(x_newsreader,"NewsCoaster (v%s) (Unregistered)",version);
		else
			sprintf(x_newsreader,"NewsCoaster (v%s) [Amiga, 68k] by Mark Harman (Unregistered)",version);
	}*/
	char date[256] = "";
	//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);
	/*strncpy(write->newmessage.to,getstr(write->STR_write_TO),NEWMESS_long);
	write->newmessage.to[NEWMESS_long] = '\0';*/
	strncpy(write->newmessage.newsgroups,getstr(write->STR_write_NG),NEWMESS_long);
	write->newmessage.newsgroups[NEWMESS_long] = '\0';
	strncpy(write->newmessage.followup,getstr(write->STR_write_FOLLOWUP),NEWMESS_long);
	write->newmessage.followup[NEWMESS_long] = '\0';
	strncpy(write->newmessage.from,getstr(write->STR_write_FROM),NEWMESS_long);
	write->newmessage.from[NEWMESS_long] = '\0';

	//Server *server = getPostingServer();
	Server *server = getPostingServerForGroup(write->newmessage.newsgroups);
	//printf("server: %s\n",server->nntp);
	create_mID(write->newmessage.messageID,write->newmessage.from,server->nntp);

	strncpy(write->newmessage.subject,getstr(write->STR_write_SUBJECT),NEWMESS_long);
	write->newmessage.subject[NEWMESS_long] = '\0';
	
	char * header = new char[10240 + textlen];
	char *hptr = header;
	int r = 0;
	r = sprintf(hptr,"From: %s\n",write->newmessage.from); hptr += r;
	//r = sprintf(hptr,"Date: %s\n",mdata->date); hptr += r;
	r = sprintf(hptr,"Date: %s\n",date); hptr += r;
	r = sprintf(hptr,"Subject: %s\n",write->newmessage.subject); hptr += r;
	if(*account.org!=0) {
		r = sprintf(hptr,"Organization: %s\n",account.org); hptr += r;
	}
	r = sprintf(hptr,"Message-ID: %s\n",write->newmessage.messageID); hptr += r;
	if(*(write->newmessage.supersedeID)!=0) {
		r = sprintf(hptr,"Supersedes: %s\n",write->newmessage.supersedeID); hptr += r;
	}
	if(write->newmessage.nrefs>0) {
		for(int k=0;k<write->newmessage.nrefs;k++) {
			//printf("%d : %s\n",k,write->newmessage.references[k]);
			if(k==0) {
				r = sprintf(hptr,"References: %s",write->newmessage.references[k]); hptr += r;
			}
			else {
				r = sprintf(hptr," %s",write->newmessage.references[k]); hptr += r;
			}
			if(write->newmessage.references[k]) {
				delete write->newmessage.references[k];
				write->newmessage.references[k]=NULL;
			}
		}
		r = sprintf(hptr,"\n"); hptr += r;
		write->newmessage.nrefs=0;
	}
	r = sprintf(hptr,"X-Newsreader: %s\n",x_newsreader); hptr += r;
	// email and/or newsgroup posting
	mdata->flags[4]=FALSE;
	mdata->flags[5]=FALSE;
	/*if(*(write->newmessage.to)!=0) {
		mdata->flags[5]=TRUE;
		r = sprintf(hptr,"To: %s\n",write->newmessage.to); hptr += r;
	}*/
	char *toptr = getstr(write->STR_write_TO);
	if( *toptr != '\0' ) {
		mdata->flags[5] = TRUE;
		r = sprintf(hptr,"To: %s\n",toptr); hptr += r;
	}
	if(*(write->newmessage.newsgroups)!=0) {
		mdata->flags[4]=TRUE;
		r = sprintf(hptr,"Newsgroups: %s\n",write->newmessage.newsgroups); hptr += r;
	}
	if(*(write->newmessage.followup)!=0) {
		r = sprintf(hptr,"Followup-To: %s\n",write->newmessage.followup); hptr += r;
	}
	r = sprintf(hptr,"Mime-Version: 1.0\n"); hptr += r;
	if(multipart==0) {
		//strcpy(mdata->type,"text/plain");
		if(bit7) {
			r = sprintf(hptr,"Content-Type: text/plain; charset=us-ascii\n"); hptr += r;
			r = sprintf(hptr,"Content-Transfer-Encoding: 7bit\n"); hptr += r;
		}
		else {
			r = sprintf(hptr,"Content-Type: text/plain; charset=iso-8859-1\n"); hptr += r;
			r = sprintf(hptr,"Content-Transfer-Encoding: 8bit\n"); hptr += r;
		}
	}
	else {
		//strcpy(mdata->type,"multipart/mixed");
		sprintf(boundary,"BOUNDARY.NC%d.%d",rand() % 65536,mdata->messageID);
		r = sprintf(hptr,"Content-Type: multipart/mixed; boundary=\"%s\"\n",boundary); hptr += r;
	}
	if( account.xno==1 || (account.xno==2 && write->newmessage.xno==TRUE) ) {
		r = sprintf(hptr,"X-No-Archive: yes\n"); hptr += r;
	}
	GroupData * gdata_this = NULL;
	get_gdata(&gdata_this,write->newmessage.newsgroups);
	if(gdata_this!=NULL) {
		if(gdata_this->moreflags[0]==TRUE) {
			r = sprintf(hptr,"Approved: %s\n",gdata_this->appv_hd); hptr += r;
		}
	}
	r = sprintf(hptr,"\n"); hptr += r;
	int headerlen = hptr - header;
	//int headerlen = strlen(header);

	strncpy(mdata->from,write->newmessage.from,IHEADENDSHORT);
	mdata->from[IHEADENDSHORT] = '\0';
	strncpy(mdata->subject,write->newmessage.subject,IHEADENDSUBJECT);
	mdata->subject[IHEADENDSUBJECT] = '\0';
	strncpy(mdata->newsgroups,write->newmessage.newsgroups,IHEADENDSHORT);
	mdata->newsgroups[IHEADENDSHORT] = '\0';
	strncpy(mdata->messageID,write->newmessage.messageID,IHEADENDMID);
	mdata->messageID[IHEADENDMID] = '\0';
	//mdata->mIDhash = calculate_mID_hash(mdata->messageID);
	mdata->size = 0;
	char *attachments[1024];
	char *attachout = NULL;
	char *output = NULL;
	int len = headerlen + textlen + 8192;
	if(multipart==0) {
		output = header;
		strcpy(&output[headerlen],(char *)text);
	}
	else {
		MIMEType *mime[1024];
		int lengths[1024];
		int maxlen = 0;
		int k=0;

		for(k=0;k<multipart;k++) {
			DoMethod(write->NLIST_write_ATT,MUIM_NList_GetEntry,k,&mime[k]);
			BPTR lock=Lock(mime[k]->file,ACCESS_READ);
			BPTR file=Open(mime[k]->file,MODE_OLDFILE);
			if(file) {
				FileInfoBlock *fib=(FileInfoBlock *)AllocDosObject(DOS_FIB,NULL);
				Examine(lock,fib);
				lengths[k] = fib->fib_Size;
				if(lengths[k]>maxlen)
					maxlen = lengths[k];
				attachments[k] = new char[ lengths[k] + 1024 ];
				if(attachments[k] != NULL) {
					int read = Read(file,attachments[k],lengths[k]);
					attachments[k][read] = 0;
					len+=(lengths[k]*5)/3+1024;
				}
				else {
					nLog("Error! Not enough RAM for attachments!\n");
					printf("Error! Not enough RAM for attachments!\n");
				}
				if(fib) {
					FreeDosObject(DOS_FIB,fib);
					fib=NULL;
				}
				Close(file);
				file=NULL;
			}
			else {
				sprintf(buffer,"\33cCannot find file to attach:\n%s",mime[k]->file);
				MUI_RequestA(app,0,0,"Write Message","_Continue",buffer,0);
				mime[k]=NULL;
			}
			if(lock) {
				UnLock(lock);
				lock=NULL;
			}
		}
		output = new char[len];
		attachout = new char[(maxlen*5)/3+8192];
		sprintf(output,"%s\n",header);
		sprintf(output,"%sWarning: This is a message in MIME format. Your newsreader does not support\nMIME. You may still be able to read some parts as plain text, but to read\nthe rest, you need to upgrade your newsreader.\n",output);
		/*sprintf(output,"%sWarning: This is a message in MIME format. Your newsreader does not support\nMIME. You may still be able to read some parts as plain text, but to read\nthe rest, you need to upgrade your newsreader. Here are some newsreaders\nthat support MIME:\n",output);
		sprintf(output,"%s     Amiga - NewsCoaster\n       - http://members.tripod.com/Mark_Harman/newscoaster.html\n",output);
		sprintf(output,"%s     Windows - \n",output);
		sprintf(output,"%s     Unix - \n",output);*/
		if(*text!=0) {
			sprintf(output,"%s\n--%s\n",output,boundary);
			if(bit7) {
				sprintf(output,"%sContent-Type: text/plain; charset=us-ascii\n",output);
				sprintf(output,"%sContent-Transfer-Encoding: 7bit\n\n",output);
			}
			else {
				sprintf(output,"%sContent-Type: text/plain; charset=iso-8859-1\n",output);
				sprintf(output,"%sContent-Transfer-Encoding: 8bit\n\n",output);
			}
			sprintf(output,"%s%s",output,text);
		}
		for(k=0;k<multipart;k++) {
			if(mime[k]) {
				sprintf(output,"%s\n--%s\n",output,boundary);
				sprintf(output,"%sContent-Type: %s; name=\"%s\"\n",output,mime[k]->type,mime[k]->shortname);
				sprintf(output,"%sContent-Disposition: attachment; filename=\"%s\"\n",output,mime[k]->file);
				sprintf(output,"%sContent-Transfer-Encoding: %s\n\n",output,"base64");
				lengths[k]=encode_base64(attachments[k],attachout,lengths[k]);
				sprintf(output,"%s%s\n",output,attachout);
			}
		}
		sprintf(output,"%s\n--%s--\n",output,boundary);
	}

	//save file
	createMessage(gdata,mdata,output);

	if(multipart>0) {
		for(int k=0;k<multipart;k++) {
			if(attachments[k]) {
				delete [] attachments[k];
				attachments[k]=NULL;
			}
		}
		if(attachout) {
			delete [] attachout;
			attachout=NULL;
		}
		if(output) { // only if multipart, otherwise this is same as 'header'
			delete [] output;
			output=NULL;
		}
	}
	if(text) {
		FreeVec(text); // should be a FreeVec
		text=NULL;
	}
	if(header) {
		delete [] header;
		header=NULL;
	}

	write_index_single(gdata,mdata);
	setEnabled();
	gdata->nummess++;
	GroupData * gdata2 = NULL;
	getGdataDisplayed(&gdata2);
	if(gdata2->ID==gdata->ID)
		threadView();
	/*if(write->newmessage.edit==FALSE || write->newmessage.sent==TRUE) {
		if(write->newmessage.sent==TRUE)
			gdata->nummess++;
	}*/
	redrawGdataAll();
	set(write->wnd,MUIA_Window_Sleep,FALSE);
	return mdata;
}

void WriteWindow::editMess(GroupData *gdata,MessageListData *mdata,BOOL super) {
	nLog("WriteWindow::editMess((GroupData *)%d,(MessageListData)%d,(BOOL)%d) called\n",gdata,mdata,super);
	WriteWindow *ww = new WriteWindow("NewsCoaster (editing message)");
	char buffer[1024]="";
	ww->newmessage.edit=TRUE;
	if(gdata->ID==-2)
		ww->newmessage.sent=TRUE;
	else
		ww->newmessage.sent=FALSE;
	ww->newmessage.reply=FALSE;
	strcpy(ww->newmessage.getThisHeader,"to:");
	get_refs(&(ww->newmessage),gdata,mdata,GETREFS_ALL);
	if(gdata->ID==-1)
		strcpy(ww->newmessage.messageID,mdata->messageID);
	else
		strcpy(ww->newmessage.messageID,"");
	if(super)
		strcpy(ww->newmessage.supersedeID,mdata->messageID);
	strcpy(buffer,ww->newmessage.newsgroups);
	set(ww->STR_write_NG,MUIA_String_Contents,buffer);
	//set(ww->STR_write_TO,MUIA_String_Contents,ww->newmessage.to);
	set(ww->STR_write_TO,MUIA_String_Contents,ww->newmessage.dummyHeader);
	strcpy(buffer,ww->newmessage.followup);
	set(ww->STR_write_FOLLOWUP,MUIA_String_Contents,buffer);
	set(ww->STR_write_FROM,MUIA_String_Contents,ww->newmessage.from);
	strcpy(buffer,ww->newmessage.subject);
	set(ww->STR_write_SUBJECT,MUIA_String_Contents,buffer);
	DoMethod(ww->ED_write_MESS,MUIM_TextEditor_ClearText);
	set(wnd_main,MUIA_Window_Sleep,TRUE);
	DoMethod(ww->NLIST_write_ATT,MUIM_NList_Clear);
	if(!replyedit_mess(FALSE,ww))
		return;
	set(wnd_main,MUIA_Window_Sleep,FALSE);
	set(ww->ED_write_MESS,MUIA_TextEditor_CursorY,0);
	set(ww->wnd,MUIA_Window_Open,TRUE);
	set(ww->wnd,MUIA_Window_ActiveObject,ww->ED_write_MESS);
}

void WriteWindow::cancelMess(MessageListData * mdata2) {
	nLog("WriteWindow::cancelMess((MessageListData *)mdata2) called\n",mdata2);
	GroupData * gdata = NULL;
	GroupData * gdata_sent = NULL;
	get_gdata(&gdata_sent,-2);
	NewMessage message;
	get_refs(&message,gdata_sent,mdata2,GETREFS_NONE);
	char * header = new char[10240];
	char filename[MAXFILENAME]="";
	MessageListData * mdata = new MessageListData();
	mdata->init();
	mdata->flags[0]=FALSE;
	mdata->flags[2]=FALSE;
	mdata->flags[6]=-1;
	char buffer[1024]="";

	strcpy(mdata->from,account.email);
	strcpy(mdata->newsgroups,message.newsgroups);
	mdata->size=0;
	Server *server = getPostingServer();
	create_mID(mdata->messageID,mdata->from,server->nntp);
	//mdata->mIDhash = calculate_mID_hash(mdata->messageID);
	sprintf(mdata->subject,"cancel %s",message.messageID);
	char date[256] = "";
	//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);
	sprintf(header,"From: %s\n",mdata->from);
	sprintf(header,"%sDate: %s\n",header,date);
	sprintf(header,"%sSubject: %s\n",header,mdata->subject);
	sprintf(header,"%sMessage-ID: %s\n",header,mdata->messageID);
	sprintf(header,"%sControl: cancel %s\n",header,message.messageID);
	sprintf(header,"%sNewsgroups: %s\n",header,mdata->newsgroups);
	// email and/or newsgroup posting
	mdata->flags[4]=TRUE;
	mdata->flags[5]=FALSE;
	sprintf(header,"%sMime-Version: 1.0\n",header);
	//strcpy(mdata->type,"text/plain");
	sprintf(header,"%sContent-Type: text/plain; charset=us-ascii\n",header);
	sprintf(header,"%sContent-Transfer-Encoding: 7bit\n",header);
	if( account.xno==1 )
		sprintf(header,"%sX-No-Archive: yes\n",header);
	sprintf(header,"%s\n",header);
	char *output=NULL;
	int len = strlen(header)+8192;

	output = new char[len];
	sprintf(output,"%sThis message has been cancelled.",header);

	//save file
	get_gdata(&gdata,-1);
	createMessage(gdata,mdata,output);
	if(output) {
		delete [] output;
		output=NULL;
	}
	if(header) {
		delete [] header;
		header=NULL;
	}

	write_index_single(gdata,mdata);
	gdata->nummess++;
	GroupData * gdata2 = NULL;
	getGdataDisplayed(&gdata2);
	if(gdata2->ID==gdata->ID)
		threadView();
	redrawGdataAll();
}

void WriteWindow::create_mID(char * str,char * email,char * nntp) {
	nLog("WriteWindow::create_mID((char *)%d,(char *)%s,(char *)%s) called\n",str,email,nntp);
	struct DateStamp ds;
	DateStamp(&ds);
	get_email(status_buffer_g,email,GETEMAIL_EMAIL);
	STRPTR t=strchr(status_buffer_g,'@');
	if(t)
		*t=0;
	if(*nntp!=0)
		sprintf(str,"<%d%d%d%d.NC-%s.%s@%s>",ds.ds_Days,ds.ds_Minute,rand() % 65536,account.sentID,version,status_buffer_g,nntp);
	else
		sprintf(str,"<%d%d%d%d.NC-%s.%s@anywhere.com>",ds.ds_Days,ds.ds_Minute,rand() % 65536,account.sentID,version,status_buffer_g);
}

BOOL WriteWindow::createMessage(GroupData *gdata,MessageListData *mdata,char *message) {
	nLog("WriteWindow::createMessage((GroupData *)%d,(MessageListData *)%d,(char *)%d) called\n",gdata,mdata,message);
	static char filename[MAXFILENAME]="";
	BPTR file = NULL;
	BOOL rtn = FALSE;
	for(;;) {
		sprintf(filename,"NewsCoasterData:outgoing/news_%d",gdata->nextmID);
		if(!exists(filename) && (file=Open(filename,MODE_NEWFILE)) != NULL)
			break;
		gdata->nextmID++;
	}
	mdata->ID=gdata->nextmID;
	if(file) {
		int lenm=strlen(message);
		Write(file,message,lenm);
		mdata->size+=lenm;
		gdata->nextmID++;
		account.sentID++;
		redrawGdataAll();
		Close(file);
		file = NULL;
		rtn = TRUE;
	}
	return rtn;
}

BOOL WriteWindow::replyedit_mess(BOOL reply,WriteWindow * ww,GroupData * gdata,MessageListData * mdata,void *source) {
	nLog("WriteWindow::replyedit_mess((BOOL)%d,(WriteWindow *)%d,(GroupData *)%d,(MessageListData *)%d,(void *)%d) called\n",reply,ww,gdata,mdata,source);
	nLog("  %d : %d",gdata->ID,mdata->ID);
	//reply: TRUE=reply, FALSE=edit
	int type = reply ? 1 : 2;

	set(ww->ED_write_MESS,MUIA_TextEditor_ExportWrap,account.linelength);
	if(mdata->flags[12]==TRUE) {
		//we need to download the BODY!
		/*if(delete_dis)
		{
			MUI_RequestA(app,0,0,"Downloading Message","_Okay","\33cNewsCoaster cannot download articles whilst\nother messages are already being downloaded, sorry.",0);
			return FALSE;
		}
		else*/
		BOOL available = TRUE;
		if(!getBody(&available,gdata,mdata))
			return FALSE;
	}
	// update flags to read after having displayed message, since it takes time
	int multipart=0; //0=no, 1=yes
	int begin=0; //0=no, 1=yes
	BOOL uufile=FALSE;
	char cenc[64]="7bit";
	char cname[64]="";
	char cfile[64]="";
	BOOL ctype_HTML = FALSE;
	BOOL ctype_VIEW = TRUE;
	BOOL cenc_QP = FALSE;
	char ctype[256]="";
	STRPTR entry=NULL;
	int currpart=2;
	int cpos=0;
	/*
	strcpy(ctype,mdata->type);
	if(*ctype==0)
		strcpy(ctype,"text/plain");
	else if(stricmp(ctype,"text/html")==0)
		ctype_HTML = TRUE;
	else if(stricmp(ctype,"text/plain")!=0)
		ctype_VIEW = FALSE;
	if(strncmp("multipart/",mdata->type,10)==0) {
		multipart=1;
		strcpy(ctype,"");
		strcpy(cenc,"");
		strcpy(cname,"");
		strcpy(cfile,"");
	}
	*/
	char boundary[256]="--";

	set(ww->wnd,MUIA_Window_Sleep,TRUE);
	set(ww->ED_write_MESS,MUIA_TextEditor_Quiet,TRUE);

	//char buffer[4097] = "";
	char buffer2[1251] = "";
	char buffer3[1251] = "";

	char filename[256] = "";
	getFilePath(filename,gdata->ID,mdata->ID);
	nLog("  about to open file\n");
	BPTR lock = Lock(filename,ACCESS_READ);
	BPTR file = Open(filename,MODE_OLDFILE);
	if(file==NULL) {
		sprintf(status_buffer_g,"\33cError in replyedit_mess()! - Can't open file: %s\n",filename);
		MUI_RequestA(::app,0,0,"Read Message","_Okay",status_buffer_g,0);
		if(ww!=NULL) {
			set(ww->wnd,MUIA_Window_Sleep,FALSE);
			set(ww->ED_write_MESS,MUIA_TextEditor_Quiet,FALSE);
		}
		if(lock)
			UnLock(lock);
		return FALSE;
	}
	BOOL header=TRUE;
	BOOL fhd=TRUE;
	BOOL okay=TRUE;
	BOOL resethtml=TRUE;
	char word0[256];
	char word1[256];
	STRPTR str=NULL,str2=NULL,str3=NULL,str4=NULL,word2=NULL;
	STRPTR message=NULL;
	int read=0;
	LONG result=0;
	BOOL nl=FALSE;
	BOOL *line=NULL;
	int partno=0;
	BOOL quot=FALSE;
	int fibsize=0,val=0;
	STRPTR reptexts=NULL;
	STRPTR reptexte=NULL;
	char tempbuffer[8]="";
	char *big_buffer = new char[big_bufsize_g + 1];

	{
		FileInfoBlock * fib=(FileInfoBlock *)AllocDosObject(DOS_FIB,NULL);
		if(fib==NULL) {
			nLog("Error! Not enough RAM to read message (FileInfoBlock)!\n");
			printf("Error! Not enough RAM to read message (FileInfoBlock)!\n");
			delete [] big_buffer;
			return FALSE;
		}
		Examine(lock,fib);
		fibsize=fib->fib_Size;
		FreeDosObject(DOS_FIB,fib);
		fib = NULL;
		message = new char[fibsize+1024];
		if(message==NULL) {
			sprintf(status_buffer_g,"Error! Not enough RAM to read message!\n");
			MUI_RequestA(::app,0,0,"Read Message","_Okay",status_buffer_g,0);
			if(file)
				Close(file);
			if(lock)
				UnLock(lock);
			delete [] big_buffer;
			return FALSE;
		}
		Flush(file);
		// header
		for(;;) {
			if(!FGets(file,big_buffer,big_bufsize_g))
				break;
			if(big_buffer[0]==10 || big_buffer[0]==13)
				break;

			int word0len=wordFirstAndLen(word0,big_buffer);
			okay=FALSE;
			if(word0[word0len-1]==':') {
				word0[word0len-1]=0;
				if(account.readheader_type!=0) {
					if(account.readheader_type==2)
						okay=TRUE;
					else {
						if(stristr(account.readheaders,word0)!=NULL)
							okay=TRUE;
					}
				}
			}
			if(stricmp(word0,"Content-Transfer-Encoding")==0) {
				word(cenc,big_buffer,2);
				if(stricmp(cenc,"Quoted-Printable")==0)
					cenc_QP = TRUE;
				else
					cenc_QP = FALSE;
			}
			else if(stricmp(word0,"Content-Type")==0) {
				word(ctype,big_buffer,2);
				if(*ctype != '\0') {
					StripChar(ctype,';');
				}
			}
			//if(multipart==1)
			{
				str=strstr(big_buffer,"boundary=\"");
				if(str) {
					str+=10;
					str2=strchr(str,'\"');
					strncpy(&boundary[2],str,(int)(str2-str));
					boundary[(int)(str2-str)+2]=0;
				}
				else {
					str=strstr(big_buffer,"boundary=");
					if(str) {
						str+=9;
						str2=strchr(str,' ');
						if(str2==NULL)
							str2=&big_buffer[strlen(big_buffer)];
						strncpy(&boundary[2],str,(int)(str2-str));
						boundary[(int)(str2-str)+2]=0;
					}
				}
			}
		}

	if(*ctype=='\0')
		strcpy(ctype,"text/plain");
	else if(stricmp(ctype,"text/html")==0)
		ctype_HTML = TRUE;
	else if(stricmp(ctype,"text/plain")!=0)
		ctype_VIEW = FALSE;
	if(strncmp("multipart/",ctype,10)==0) {
		multipart = 1;
		strcpy(ctype,"");
		strcpy(cenc,"");
		strcpy(cname,"");
		strcpy(cfile,"");
	}
	//printf("%s\n",ctype);

		// body
		{
			nLog("  reading body\n");
			for(;;) {
				if(!FGets(file,big_buffer,big_bufsize_g))
					break;
				if(multipart==1)
					str=strstr(big_buffer,boundary);
				else
					str = NULL;
				if(str!=NULL) {
					if(strncmp(&str[strlen(boundary)],"--",2)==0) {
						strcpy(ctype,"");
						break;
					}
					strcpy(ctype,"text/plain"); // default
					ctype_VIEW = TRUE;
					ctype_HTML = FALSE;
					strcpy(cname,"Unnamed");
					for(;;) { // sub-header
						if(!FGets(file,big_buffer,big_bufsize_g))
							break;
						StripNewLine(big_buffer);
						if(*big_buffer==0)
							break;
						wordFirst(word1,big_buffer);
						if(*word1 != NULL) {
							if(stricmp(word1,"Content-Type:")==0) {
								word(ctype,big_buffer,2);
								if(*ctype != NULL) {
									StripChar(ctype,';');
									if(stricmp(ctype,"text/plain")==0) {
										ctype_VIEW = TRUE;
										ctype_HTML = FALSE;
									}
									else if(stricmp(ctype,"text/html")==0) {
										ctype_VIEW = TRUE;
										ctype_HTML = TRUE;
									}
									else {
										ctype_VIEW = FALSE;
										ctype_HTML = FALSE;
									}
								}
								strcpy(buffer2,big_buffer);
								str=strstr(buffer2,"name=");
								if(str) {
									str2=strchr(str,' ');
									if(str2==NULL)
										str2=&str[strlen(str)];
									strncpy(buffer3,str,6);
									buffer3[6]=0;
									if(stricmp(buffer3,"name=\"")==0) {
										str2[-1]=0;
										strcpy(cname,&str[6]);
									}
									else {
										buffer3[5]=0;
										if(stricmp(buffer3,"name=")==0)
										{
											*str2=0;
											strcpy(cname,&str[5]);
										}
									}
								}
							}
							if(stricmp(word1,"Content-Disposition:")==0) {
								strcpy(buffer2,big_buffer);
								str=strstr(buffer2,"filename=");
								if(str) {
									str2=strchr(str,' ');
									if(str2==NULL)
										str2=&str[strlen(str)];
									strncpy(buffer3,str,10);
									buffer3[10]=0;
									if(stricmp(buffer3,"filename=\"")==0) {
										str2[-1]=0;
										strcpy(cfile,&str[10]);
									}
									else {
										buffer3[9]=0;
										if(stricmp(buffer3,"filename=")==0) {
											*str2=0;
											strcpy(cfile,&str[9]);
										}
									}
								}
							}
							if(stricmp(word1,"Content-Transfer-Encoding:")==0) {
								word(cenc,big_buffer,2);
								if(stricmp(cenc,"Quoted-Printable")==0)
									cenc_QP = TRUE;
								else
									cenc_QP = FALSE;

								if(stricmp(cenc,"base64")==0)
									ctype_VIEW = FALSE;
							}
						}
					}
					if(type==2) {
						if(ctype_VIEW == FALSE) {
							MIMEType *mime = new MIMEType;
							strcpy(mime->file,cfile);
							exfile(mime);
							strcpy(mime->type,ctype);
							DoMethod(ww->NLIST_write_ATT,MUIM_NList_InsertSingle,mime,MUIV_NList_Insert_Bottom);
						}
					}
				}
				else {
					{
						nl=TRUE;
						if(type==1)
							nl=FALSE;
						if(cenc_QP) {
							decode_qprint(big_buffer,buffer2,strlen(big_buffer),nl);
							strcpy(big_buffer,buffer2);
						}
						if(ctype_HTML) {
							parse_html(big_buffer,buffer2,strlen(big_buffer),resethtml);
							resethtml=FALSE;
							strcpy(big_buffer,buffer2);
						}
						if(ctype_VIEW) {
							if(type==1) {
								strcpy(&message[cpos],big_buffer);
								cpos+=strlen(big_buffer);
							}
							else if(type==2) {
								strcpy(&message[cpos],big_buffer);
								cpos+=strlen(big_buffer);
							}
						}
					}
				}
			}
			nLog("  done : %d\n",cpos);
		}
	}
	message[cpos]=0;
	str=message;
	if((account.flags & Account::SNIPSIG)!=0 && type==1) {
		str3=strstr(message,"\n-- \n");
		if(str3==NULL) {
			if(strncmp(message,"-- \n",4)==0)
				str3=message;
		}
		if(str3==NULL)
			str3=&message[cpos-1];
	}
	else
		str3=&message[cpos-1];
	if(str3>message) {
		if(account.rewrap==1) {
			quot=FALSE;
			do {
				while(*str=='\n')
					str++;
				if(*str=='>' || *str=='|' || *str==':' || *str=='!')
					quot=TRUE;
				else
					quot=FALSE;
				str2=strchr(str,'\n');
				if(str2==NULL || str2>str3)
					break;
				if(str2-str<40) { // this line is less than 40 chars in width, so probably an intended newline
					str=str2+1;
				}
				else {
					if(!isspace(str2[1]) && str2[1]!='>' && str2[1]!='|' && str2[1]!=':' && str2[1]!='!') {
						if(quot==FALSE)
							*str2=' ';
						else
							quot=FALSE;
						str=str2+1;
					}
					else {
						str=str2+1;
						while(*str=='\n')
							str++;
					}
				}
				if(str[0]==0)
					break;
			} while(1);
			str=message;
			if(type==1) {
				do {
					str2=strchr(str,'\n');
					if(*str!='>' && *str!='|' && *str!=':' && *str!='!') {
						if(str2>str+account.linelength-4 || str2==NULL) {
							str2=str+account.linelength-4; // get a line length
							str4=str;
							do { // cope with tabs
								if(*str4++=='\t') {
									str2-=TAB;
								}
							} while(str4<=str2);
							while(*str2>32) // go to previous whitespace
								str2--;
							if(str2<=str) // line is bigger than line width
								str2=str+account.linelength-4; // so split it
						}
					}
					if(str2>str3) // past end of message
						str2=str3;
					read=(int)(str2-str+1);
					strncpy(big_buffer,str,read);
					if(*str2=='\n')
						big_buffer[read]=0;
					else {
						if( read > 0 && isspace(big_buffer[read-1]) ) {
							big_buffer[read-1] = '\0';
							read--;
						}
						big_buffer[read]='\n';
						big_buffer[read+1]=0;
					}
					DoMethod(ww->ED_write_MESS,MUIM_TextEditor_InsertText,"> ",MUIV_TextEditor_InsertText_Bottom);
					DoMethod(ww->ED_write_MESS,MUIM_TextEditor_InsertText,big_buffer,MUIV_TextEditor_InsertText_Bottom);
					str=str2+1;
				} while(str2<str3);
			}
			else
				DoMethod(ww->ED_write_MESS,MUIM_TextEditor_InsertText,message,MUIV_TextEditor_InsertText_Bottom);
		}
		else {
			if(type==1) {
				do {
					str2=strchr(str,'\n');
					if(str2>str3 || str2==NULL)
						str2=str3;
					read=(int)(str2-str+1);
					strncpy(big_buffer,str,read);
					big_buffer[read]=0;
					DoMethod(ww->ED_write_MESS,MUIM_TextEditor_InsertText,"> ",MUIV_TextEditor_InsertText_Bottom);
					DoMethod(ww->ED_write_MESS,MUIM_TextEditor_InsertText,big_buffer,MUIV_TextEditor_InsertText_Bottom);
					str=str2+1;
				} while(str2!=str3);
			}
			else
				DoMethod(ww->ED_write_MESS,MUIM_TextEditor_InsertText,message,MUIV_TextEditor_InsertText_Bottom);
		}
	}
	nLog("  about to close file\n");
	if(file) {
		Close(file);
		file=NULL;
	}
	if(lock) {
		UnLock(lock);
		lock=NULL;
	}
	set(ww->ED_write_MESS,MUIA_TextEditor_Quiet,FALSE);
	set(ww->wnd,MUIA_Window_Sleep,FALSE);
	nLog("  about to delete parts ( %d )\n",currpart);
	if(message) {
		delete [] message;
		message=NULL;
	}
	// update flags to READ
	if(mdata->flags[1]==TRUE) {
		mdata->flags[1]=FALSE; // no longer NEW
		gdata->num_unread--;
		update_screen_title(gdata);
		
		if(gdata->flags[6]!=0)
			gdata->flags[1]=TRUE; // still mark to rewrite index if we are discarding messages
		nLog("  about to call redrawMdataActive()..\n");
		redrawMdataActive();
		nLog("  Succeeded!\n");
		write_index_update(gdata,mdata,source);
		
	}
	delete [] big_buffer;
	nLog("  finished replyedit_mess()\n");
	return TRUE;
}

BOOL WriteWindow::replyedit_mess(BOOL reply,WriteWindow * ww) {
	GroupData * gdata = NULL;
	MessageListData * mdata = NULL;
	getGdataDisplayed(&gdata);
	getMdataActive(&mdata);
	return WriteWindow::replyedit_mess(reply,ww,gdata,mdata,NLIST_messagelistdata);
}

void WriteWindow::reply(GroupData * gdata,MessageListData * mdata,void *source,BOOL followup,BOOL reply) {
	nLog("WriteWindow::reply((GroupData *)%d,(MessageListData *)%d,(void *)%d,(BOOL)%d,(BOOL)%d) called\n",gdata,mdata,source,followup,reply);
	int result = 0;
	char buffer[NEWMESS_long+3]="";
	char buffer2[NEWMESS_long+1]="";
	char temp[1024] = "";
	struct DateStamp ds;
	DateStamp(&ds);
	const int stupidage = 90;
	if(ds.ds_Days - mdata->ds.ds_Days > stupidage) {
		// stupidity warning - warns against replying to old posts
		MUI_RequestA(::app,0,0,"Old Message!","_Okay","\33cI am just warning you that you are replying\nto a rather old post!",0);
	}

		WriteWindow *ww = new WriteWindow("NewsCoaster");
			DoMethod(ww->NLIST_write_ATT,MUIM_NList_Clear);
			/*if(gdata->ID >= 0)
				set(ww->CY_write_SIG,MUIA_Cycle_Active,gdata->defsig+1);
			else
				set(ww->CY_write_SIG,MUIA_Cycle_Active,1);*/
			set(ww->STR_write_FOLLOWUP,MUIA_String_Contents,"");
			getUserEmail(gdata,buffer);
			set(ww->STR_write_FROM,MUIA_String_Contents,buffer);
			strcpy(ww->newmessage.getThisHeader,"reply-to:");
			get_refs(&(ww->newmessage),gdata,mdata,GETREFS_ALL);
			if(reply==FALSE && stristr_q(ww->newmessage.followup,"POSTER")!=NULL) {
				result=MUI_RequestA(::app,0,0,"Write Message","_Followup to Newsgroup|_Reply via email","\33cThe author requested that he be replied to via email.\nIt may be better to do so.",0);
		 		switch(result) {
		 			case 1:
		 				reply=FALSE;
	 					followup=TRUE;
	 					break;
	 				case 0:
	 					reply=TRUE;
	 					followup=FALSE;
	 					break;
	 			}
			}
			//printf("%d\n",ww->newmessage.nrefs);
			char *newrefptr = new char[257];
			ww->newmessage.references[ww->newmessage.nrefs++] = newrefptr;
			strncpy(newrefptr,ww->newmessage.messageID,256);
			newrefptr[256] = '\0';
			//printf("%d:%s\n",ww->newmessage.references[0],ww->newmessage.references[0]);
			ww->newmessage.edit=FALSE;
			ww->newmessage.reply=TRUE;
			ww->newmessage.replied_gdataID=gdata->ID;
			ww->newmessage.replied_mdataID=mdata->ID;
			strcpy(ww->newmessage.messageID,"");
			if(followup) {
				if(*(ww->newmessage.followup)!=0 && stristr_q(ww->newmessage.followup,"POSTER")==NULL) {
					strcpy(buffer,ww->newmessage.followup);
				}
				else
					strcpy(buffer,ww->newmessage.newsgroups);
				set(ww->STR_write_NG,MUIA_String_Contents,buffer);
			}
			else
				set(ww->STR_write_NG,MUIA_String_Contents,"");
			if(reply) {
				/*if(*(ww->newmessage.replyto)!=0)
					strcpy(buffer,ww->newmessage.replyto);
				else
					strcpy(buffer,ww->newmessage.from);*/
				if(*(ww->newmessage.dummyHeader) != '\0')
					strcpy(buffer,ww->newmessage.dummyHeader);
				else
					strcpy(buffer,ww->newmessage.from);
				set(ww->STR_write_TO,MUIA_String_Contents,buffer);
			}
			else
				set(ww->STR_write_TO,MUIA_String_Contents,"");
			wordFirst(temp,ww->newmessage.subject);
			if(stricmp(temp,"Re:")!=0 && stricmp(temp,"Sv:")!=0)
				sprintf(buffer,"Re: %s",ww->newmessage.subject);
			else
				strcpy(buffer,ww->newmessage.subject);
			set(ww->STR_write_SUBJECT,MUIA_String_Contents,buffer);
			set(ww->wnd,MUIA_Window_Open,TRUE);
			set(ww->wnd,MUIA_Window_Sleep,TRUE);
			DoMethod(ww->ED_write_MESS,MUIM_TextEditor_ClearText);
			set(ww->wnd,MUIA_Window_ActiveObject,ww->ED_write_MESS);
			if(!WriteWindow::replyedit_mess(TRUE,ww,gdata,mdata,source)) {
				set(ww->wnd,MUIA_Window_Sleep,FALSE);
				set(ww->wnd,MUIA_Window_Open,FALSE);
				return;
			}
			// insert .sig
			/*if(gdata->defsig>=0) {
				strcpy(buffer,"-- \n");
				DoMethod(ww->ED_write_MESS,MUIM_TextEditor_InsertText,buffer,MUIV_TextEditor_InsertText_Bottom);
				if(gdata->ID>=0 && sigs[gdata->defsig]!=NULL)
					DoMethod(ww->ED_write_MESS,MUIM_TextEditor_InsertText,sigs[gdata->defsig],MUIV_TextEditor_InsertText_Bottom);
				else {
					if(sigs[0])
						DoMethod(ww->ED_write_MESS,MUIM_TextEditor_InsertText,sigs[0],MUIV_TextEditor_InsertText_Bottom);
				}
			}*/
			if(gdata->ID >= 0)
				set(ww->CY_write_SIG,MUIA_Cycle_Active,gdata->defsig+1);
			else
				set(ww->CY_write_SIG,MUIA_Cycle_Active,1);

			get_email(buffer2,ww->newmessage.from,GETEMAIL_NAMEEMAIL);
			char *strptr[16];
			char fbuffer[256];
			char percent[] = "%";
			sprintf(fbuffer,"%s\n\n",account.followup_text);
			char *ptr = fbuffer;
			int cptr=0;
			for(;;) {
				ptr = strchr(ptr,'%');
				if(ptr==NULL)
					break;
				ptr++;
				BOOL okay=TRUE;
				if(cptr<16) {
					if(*ptr=='n')
						strptr[cptr++] = buffer2;
					else if(*ptr=='d')
						strptr[cptr++] = ww->newmessage.date;
						//strptr[cptr++] = mdata->date;
					else if(*ptr=='g')
						strptr[cptr++] = mdata->newsgroups;
					else if(*ptr=='m')
						strptr[cptr++] = mdata->messageID;
					else if(*ptr=='%')
						strptr[cptr++] = percent;
					else
						okay=FALSE;
				}
				else
					okay=FALSE;
				if(okay)
					*ptr='s';
				else {
					ptr[-1] = ' ';
					ptr[0] = ' ';
				}
			}
			sprintf(buffer,fbuffer,strptr[0],
				strptr[1],
				strptr[2],
				strptr[3],
				strptr[4],
				strptr[5],
				strptr[6],
				strptr[7],
				strptr[8],
				strptr[9],
				strptr[10],
				strptr[11],
				strptr[12],
				strptr[13],
				strptr[14],
				strptr[15]);
			set(ww->ED_write_MESS,MUIA_TextEditor_CursorX,0);
			set(ww->ED_write_MESS,MUIA_TextEditor_CursorY,0);
			DoMethod(ww->ED_write_MESS,MUIM_TextEditor_InsertText,buffer,MUIV_TextEditor_InsertText_Cursor);
			set(ww->ED_write_MESS,MUIA_TextEditor_CursorY,0);
			set(ww->wnd,MUIA_Window_Sleep,FALSE);
	/*}
	else
		MUI_RequestA(app,0,0,"Write Message","_Okay","\33cYou may only write one message\nat a time.\nPlease finish/cancel the\nexisting message.",0);*/
}

void WriteWindow::reply(BOOL followup,BOOL reply) {
	GroupData * gdata = NULL;
	MessageListData * mdata = NULL;
	int result = 0;
	getMdataActivePos(&result);
	if(result!=MUIV_NList_Active_Off) {
		getGdataDisplayed(&gdata);
		getMdataActive(&mdata);
		WriteWindow::reply(gdata,mdata,NLIST_messagelistdata,followup,reply);
	}
	else
		MUI_RequestA(::app,0,0,"Write Message","_Okay","\33cYou must first select a message to followup/reply to!",0);
}

void WriteWindow::freeStatics() {
	nLog("WriteWindow::freeStatics() called\n");
	int size=ptrs->getSize();
	WriteWindow ** data = (WriteWindow **)ptrs->getData();
	for(int i=0;i<size;i++)
		delete data[i];
	delete ptrs;

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