/* $Id: msg.cpp,v 1.24 2004/01/02 04:05:36 fesnel Exp $ */
/*******************************************************************************
 *   This program is part of the XFMail email client.                          *
 *                                                                             *
 *   Copyright : (C) 1995-1998 Gennady B. Sorokopud (gena@NetVision.net.il)    *
 *               (C) 1995 Ugen. J. S. Antsilevich (ugen@latte.worldbank.org)   *
 *               (C) 1998-2004 by the Archimedes Project                       *
 *                   http://sourceforge.net/projects/archimedes                *
 *                                                                             *
 *             --------------------------------------------                    *
 *                                                                             *
 *   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.  *
 *                                                                             *
 *   Additional Permission granted:                                            *
 *                                                                             *
 *   This program is designed to use the XForms library, so we consider        *
 *   permission to link to that non-GPL-compatible library is implicit.        *
 *   However, in case this is not considered so, we explicitly state:          *
 *                                                                             *
 *   "As a special exception, the Archimedes Project, with the permission      *
 *    of all earlier copyright holders, formally gives permission to link      *
 *    this program with the XForms library, and distribute the resulting       *
 *    executable without the source code for XForms in the source              *
 *    distribution".                                                           *
 *                                                                             *
 ******************************************************************************/


#include <fmail.h>
#include <umail.h>
#include <choose_folder.h>

#include "addrbook_util.h"
#include "uucode.h"

#define MSG_XPM
#include <X11/xpm.h>
#include <pixmaps.h>
#include <fl_edit.h>
#include <spellchecker.h>

#ifdef HAVE_REGCOMP
	#include <regex.h>
#else
	#include "../regex/regex.h"
#endif

#define MAX_MSG_FORMS       15

#define EDIT_MENU   "Insert file (Alt+I)|Uuencode file|Save to File|Append to File%l|Sign Message (Alt+N)|Quote original (Alt+Q)|Spelling check (Alt+P)"

extern cfgfile Config;

struct msg_form {
	struct _mail_msg *me_msg;
	FL_FORM *me_form;
	FL_OBJECT *me_from,
	*me_to,
	*me_to_list,
	*me_to_type,
	*me_subj,
	*me_text,
	*me_pixmap,
	*me_bitmap,
	*me_date,
	*me_mime, *me_enc, *me_pgp, *me_sign, *me_prior, *me_abort;
	int me_lang;
#define me_sender   me_to
	int me_flags;
#define MF_VIEW     0x01
#define MF_HEADER   0x02
#define MF_CHANGED  0x04
#define MF_LOCKED   0x08
#define MF_PGPSIGN  0x10
#define MF_READONLY 0x20
#define MF_BUSY     0x40
#define MF_SIGN     0x80
	u_long tofft;
};

static struct msg_form *mf_arr[MAX_MSG_FORMS];
static int mf_x = 800, mf_y = 600, mfc_x = 100, mfc_y = 100;
static int mf_xofft = 0, mf_yofft = 0;
static int num_cascade = 0;
static FL_OBJECT *tobj = NULL;
static FL_FORM *autosave = NULL;
FL_OBJECT *asave_timer = NULL;
int menuind;
int ttips = -1;


void end_msg(int op);
void destruct_msg(struct msg_form *mf);
char *form_to_msg(int num, int update);
void ext_edit_msg(int num);
void ext_edit_exit(struct _proc_info *pinfo);
void ext_fulledit_msg(int num);
void ext_fulledit_exit(struct _proc_info *pinfo);
void ext_view_msg(int num, int asis);
void display_msg_text(struct msg_form *mf);
void ext_view_exit(struct _proc_info *pinfo);
char *compose_msg_text(struct msg_form *mf, int update);
void display_addresses(int id);
struct _mail_addr *get_msgaddr_byline(int id, int line, int *type);
int update_msg(int id);
void cb_mime(FL_OBJECT * obj, long num);
void cb_msg_edit(FL_OBJECT * obj, long num);
void cb_addr_addto(FL_OBJECT * obj, long num);
void cb_mbutton_exit_edit(FL_OBJECT * obj, long num);
void cb_mbutton_delete(FL_OBJECT * obj, long num);
void cb_spell_button(FL_OBJECT * obj, long num);
void cb_pgp_encode_button(FL_OBJECT * obj, long num);
void cb_pgp_decode_button(FL_OBJECT * obj, long num);
void cb_pgp_signencode_button(FL_OBJECT * obj, long num);
void cb_pgp_sign_button(FL_OBJECT * obj, long num);
void cb_pgp_verify_button(FL_OBJECT * obj, long num);
void cb_pgp_extkey_button(FL_OBJECT * obj, long num);
void cb_pgp_addkey_button(FL_OBJECT * obj, long num);
void cb_mime_list_dbl(FL_OBJECT * obj, long num);
void cb_addr_modify(FL_OBJECT * obj, long num);
void cb_addr_list_dbl(FL_OBJECT * obj, long num);
int pgp_message(long num, int mode);
void release_orig(int id);


void msg_form_init() {
	int i;

	for(i = 0; i < MAX_MSG_FORMS; i++)
		mf_arr[i] = NULL;
	sscanf(Config.get("msgformsize", "800 600 100 100").c_str(),
		   "%d%d%d%d", &mf_x, &mf_y, &mfc_x, &mfc_y);
}

void msg_form_shutdown() {
	char buf[20];
	int i;

	cb_msg_autosave(NULL, 0);
	for(i = 0; i < MAX_MSG_FORMS; i++) {
		if(mf_arr[i])
			end_msg(i);
	}

	Config.setFlags("msgformsize", CF_NOTCHANGED);
	sprintf(buf, "%d %d %d %d", mf_x, mf_y, mfc_x, mfc_y);
	Config.set("msgformsize", buf);
}

void mf_deactivate(struct msg_form *mf) {
	if(mf == NULL)
		return;

	fl_deactivate_all_forms();
	abort_button_active(mf->me_abort, 1);
}

void mf_activate(struct msg_form *mf) {
	if(mf == NULL)
		return;

	fl_activate_all_forms();
	abort_button_active(mf->me_abort, 0);
}

void msg_deactivate(int num) {
	if(mf_arr[num] == NULL)
		return;

	fl_deactivate_all_forms();
	abort_button_active(mf_arr[num]->me_abort, 1);
}

void msg_activate(int num) {
	if(mf_arr[num] == NULL)
		return;

	fl_activate_all_forms();
	abort_button_active(mf_arr[num]->me_abort, 0);
}

void msg_text_activate(int active) {
	int i;
	FL_OBJECT *obj;
	struct msg_form *mf;

	for(i = 0; i < MAX_MSG_FORMS; i++) {
		mf = mf_arr[i];
		if((mf != NULL) && !(mf->me_flags & MF_VIEW)) {
			fl_activate_form(mf->me_form);
			for(obj = mf->me_form->first; obj; obj = obj->next) {
				if((obj == mf->me_text) || (obj == mf->me_from) ||
				   (obj == mf->me_subj) || (obj == mf->me_to))
					continue;
				if(active)
					fl_deactivate_object(obj);
				else
					fl_activate_object(obj);
			}
			fl_activate_object(mf->me_text);
			fl_activate_object(mf->me_subj);
			fl_activate_object(mf->me_from);
			fl_activate_object(mf->me_to);
		}
	}
}

void switch_ttips() {
	switch(ttips) {
		case -2:
			ttips = 1;
			break;

		case 1:
			ttips = -2;
			break;

	}
}

void cb_ttip_timer(FL_OBJECT * obj, long param) {
	if(!tobj || (ttips <= 0))
		return;

	fl_show_oneliner((char *) tobj->u_vdata, tobj->form->x + tobj->x,
					 tobj->form->y + tobj->y + tobj->h + 5);
}

int
post_handler(FL_OBJECT * ob, int event, FL_Coord mx, FL_Coord my, int key,
			 void *xev) {

	if(ob->u_vdata == NULL)
		return 0;

	if(ttips == -1)
		ttips = Config.getInt("tooltips", 1);
	if(ttips <= 0)
		return 0;

	switch(event) {
		case FL_ENTER:
			tobj = ob;
			fl_set_timer(ttip_timer, TTIP_DELAY);
			break;

		default:
			if(tobj && (event != FL_MOTION)) {
				fl_hide_oneliner();
				fl_set_timer(ttip_timer, 0);
				tobj = NULL;
			}
			break;
	}

	return 0;
}

void cb_subjedit(FL_OBJECT * obj, long num) {
	if((mf_arr[num]->me_subj == obj) && !obj->focus)
		fl_set_form_title(mf_arr[num]->me_form,
						  fl_get_input(mf_arr[num]->me_subj));
	if(mf_arr[num]->me_subj == obj)
		mf_arr[num]->me_flags |= MF_CHANGED;
}

void cb_txtedit(FL_OBJECT * obj, long num) {
	mf_arr[num]->me_flags |= MF_CHANGED;
}

void cb_msg_autosave(FL_OBJECT * obj, long num) {
	int i;

	display_msg(MSG_STAT, NULL, "Autosaving...");

	for(i = 0; i < MAX_MSG_FORMS; i++) {
		if((mf_arr[i] != NULL) &&
		   !(mf_arr[i]->me_flags & MF_VIEW) &&
		   fl_get_textedit_bufchanged(mf_arr[i]->me_text)) {
			compose_msg_text(mf_arr[i], 1);
			mf_arr[i]->me_flags |= MF_CHANGED;
			fl_set_textedit_bufchanged(mf_arr[i]->me_text, 0);
		}
	}

	display_msg(MSG_STAT, NULL, "");
	if(asave_timer)
		fl_set_timer(asave_timer,
					 Config.getInt("asavetime", 180));
}

void cb_editor(FL_OBJECT * obj, long num) {
	long res;
	int epup = fl_defpup(mf_arr[num]->me_form->window, EDIT_MENU);

	res = fl_dopup(epup);
	fl_freepup(epup);
	if(res > 0)
		cb_msg_edit(obj, -res);
}

void cb_browser(FL_OBJECT * obj, long num) {
	disp_infowindow(mf_arr[num]->me_msg, INFO_MSG);
}

int text_dbl_call(FL_OBJECT * obj, char *word, int key, int r, int cc) {
	struct _proc_info pinfo;
	char buf[255], *p, url[128];
	int extcheck = 0, ftp = 0, maddr = 0;
	struct _mail_msg *msg;

	if(((p = strstr(word, "http://")) == NULL) &&
	   ((p = strstr(word, "https://")) == NULL)) {
		if((p = strstr(word, "ftp://")) == NULL) {
			p = word;
			if(strchr(word, '@'))
				maddr = 1;
			else
				extcheck = 1;
		} else
			ftp = 1;
	}

	strncpy(url, p, 127);
	url[127] = '\0';

	if(maddr) {
		p = url + strlen(url) - 1;
		while(!isalpha(*p) && !isdigit(*p))
			*p-- = '\0';
		p = url;
		while(!isalpha(*p) && !isdigit(*p))
			p++;
		if(!display_msg(MSG_QUEST, "Send message to", "%s ?", p))
			return 0;
		if((msg = create_message(outbox)) == NULL)
			return 0;
		msg->header->To = get_address(p, 0);
		edit_msg(msg);
		refresh_folders();
		return 1;
	} else {
		if(p == word) {
			p = url + strlen(url) - 1;
			while((*p == '"') || (*p == '\'') || (*p == '>'))
				*p-- = '\0';
		} else {
			p--;
			if(*p == '"')
				p = strchr(url, '"');
			else if(*p == '\'')
				p = strchr(url, '\'');
			else if(*p == '<')
				p = strchr(url, '>');
			else if(*p == '>')
				p = strchr(url, '<');
			else if(*p == '(')
				p = strchr(url, ')');
			else if(*p == '[')
				p = strchr(url, ']');
			else
				p = NULL;

			if(p != NULL)
				*p = '\0';
		}
	}

	if(extcheck) {
		extcheck = 0;
		p = url;
		if(!isalpha(*p))
			return 0;
		while((*p != '\0') && (*p != '/')) {
			if(!isalpha(*p) && !isdigit(*p) && (*p != '.') &&
			   (*p != '_') && (*p != '-') && (*p != ':'))
				return 0;

			if(*p == '.') {
				p++;
				if((*p == '\0') || (*p == '.'))
					return 0;
				extcheck++;
				continue;
			}
			p++;
		}

		if(extcheck == 0)
			return 0;

		if(strncasecmp(url, "www.", 4)) {
			if(!display_msg
			   (MSG_QUEST, "URL", "%s looks like a URL\nStart browser?",
				url)) return 0;
		}
	}

	if(ftp) {
		if(!display_msg(MSG_QUEST, url, "Start FTP transfer?"))
			return 0;
		p = const_cast<char *>(Config.get("ftprog", "").c_str());
	} else {
		p = const_cast<char *>(Config.get("urlview", "").c_str());
		if(!p || !*p)
			p = mailcap[HTML_MAILCAP].ext_mcap;
	}

	if(!p || !*p)
		return 0;

	if(strstr(p, "%s") == NULL)
		snprintf(buf, sizeof(buf), "%s %s", p, url);
	else
		snprintf(buf, sizeof(buf), p, url, url);

	init_pinfo(&pinfo);
	pinfo.wait = WAIT_ASYNC;

	display_msg(MSG_STAT, NULL, "Started URL browser for %s", url);
	display_msg(MSG_LOG, "msgview", "Started URL browser for %s", url);
	exec_child(buf, &pinfo);

	return 1;
}

void cb_conf_delivery(FL_OBJECT * obj, long num) {
	if(!mf_arr[num])
		return;

	if(fl_get_button(obj))
		mf_arr[num]->me_msg->status |= C_DELIVERY;
	else
		mf_arr[num]->me_msg->status &= ~C_DELIVERY;
}

void cb_conf_read(FL_OBJECT * obj, long num) {
	if(!mf_arr[num])
		return;

	if(fl_get_button(obj))
		mf_arr[num]->me_msg->status |= C_READ;
	else
		mf_arr[num]->me_msg->status &= ~C_READ;
}

void cb_pgpsign(FL_OBJECT * obj, long num) {
	if(fl_get_button(obj))
		mf_arr[num]->me_flags |= MF_PGPSIGN;
	else
		mf_arr[num]->me_flags &= ~MF_PGPSIGN;
}

void cb_sign(FL_OBJECT * obj, long num) {
	if(fl_get_button(obj))
		mf_arr[num]->me_flags |= MF_SIGN;
	else
		mf_arr[num]->me_flags &= ~MF_SIGN;
}

void cb_urgent(FL_OBJECT * obj, long num) {
	if(!mf_arr[num])
		return;

	mf_arr[num]->me_msg->flags &= ~URGENT1;
	mf_arr[num]->me_msg->flags &= ~URGENT2;

	switch(fl_get_choice(obj)) {
		case 1:     /* Very high */
			mf_arr[num]->me_msg->flags |= (URGENT1 | URGENT2);
			break;

		case 2:     /* High */
			mf_arr[num]->me_msg->flags |= URGENT2;
			break;

		case 3:     /* Normal */
			break;

		case 4:     /* Low */
			mf_arr[num]->me_msg->flags |= URGENT1;
			break;
	}
}

void abook_addr_add(struct _mail_addr *adr, int type, int num) {
	struct msg_form *mf_ptr;
	struct _mail_msg *msg;
	struct _mail_addr *adr1;
	int aline;

	if(adr == NULL)
		return;
	mf_ptr = mf_arr[num];
	msg = mf_ptr->me_msg;

	if(count_recipients(msg) > MAX_RECP_NUM) {
		display_msg(MSG_WARN, "edit",
					"Can not add more then %d recipients", MAX_RECP_NUM);
		return;
	}
	adr = copy_address_chain(adr);

	aline = 1;
	switch(type) {
		case TO_TYPE:
			if(msg->header->To == NULL)
				msg->header->To = adr;
			else {
				adr1 = msg->header->To;
				aline++;
				while(adr1->next_addr != NULL) {
					aline++;
					adr1 = adr1->next_addr;
				}
				adr1->next_addr = adr;
			}
			break;
		case CC_TYPE:
			for(adr1 = msg->header->To; adr1; adr1 = adr1->next_addr)
				aline++;
			if(msg->header->Cc == NULL)
				msg->header->Cc = adr;
			else {
				adr1 = msg->header->Cc;
				aline++;
				while(adr1->next_addr != NULL) {
					aline++;
					adr1 = adr1->next_addr;
				}
				adr1->next_addr = adr;
			}
			break;
		case BCC_TYPE:
			for(adr1 = msg->header->To; adr1; adr1 = adr1->next_addr)
				aline++;
			for(adr1 = msg->header->Cc; adr1; adr1 = adr1->next_addr)
				aline++;
			if(msg->header->Bcc == NULL)
				msg->header->Bcc = adr;
			else {
				adr1 = msg->header->Bcc;
				aline++;
				while(adr1->next_addr != NULL) {
					aline++;
					adr1 = adr1->next_addr;
				}
				adr1->next_addr = adr;
			}
			break;
	}

	fl_freeze_form(mf_ptr->me_form);
	display_addresses(num);

	fl_unfreeze_form(mf_ptr->me_form);
	fl_select_browser_line(mf_ptr->me_to_list, aline);
	fl_show_browser_line(mf_ptr->me_to_list, aline);
	mf_ptr->me_flags |= MF_CHANGED;

	return;
}

void cb_addr_add(FL_OBJECT * obj, long num) {
	struct msg_form *mf_ptr;

	mf_ptr = mf_arr[num];
	if(mf_ptr->me_flags & MF_LOCKED)
		return;

	mf_ptr->me_flags |= MF_LOCKED;
	addr_book_set_placement(mf_ptr->me_form->x + mf_ptr->me_text->x,
							mf_ptr->me_form->y + mf_ptr->me_text->y);
	addr_book(NULL, abook_addr_add, num);
	mf_ptr->me_flags &= ~MF_LOCKED;

	return;
}

void cb_addr_addto(FL_OBJECT * obj, long num) {
	struct msg_form *mf_ptr;
	struct _mail_msg *msg;
	struct _mail_addr *ma = NULL, *adr1;
	struct _news_addr *naddr = NULL, *naddr1;
	struct _mail_folder *folder = NULL;
	char *addr;
	int atype = 0;

	mf_ptr = mf_arr[num];
	msg = mf_ptr->me_msg;

	if (msg == NULL)
		return;

	if(count_recipients(msg) > MAX_RECP_NUM) {
		display_msg(MSG_WARN, "edit",
					"Can not add more then %d recipients", MAX_RECP_NUM);
		fl_set_input(mf_ptr->me_to, "");
		return;
	}

	addr = (char *) fl_get_input(mf_ptr->me_to);
	atype = fl_get_choice(mf_ptr->me_to_type);

	if(!addr || !*addr) {
		return;
	}

	switch(atype) {
		case 1:
		case 2:
		case 3:
			if((ma = get_address(addr, 0)) == NULL) {
				fl_set_input(mf_ptr->me_to, "");
				return;
			}

			if((ma = expand_addr_list(mf_ptr->me_msg, ma)) == NULL) {
				fl_set_input(mf_ptr->me_to, "");
				return;
			}
			break;

		case 4:
			if((naddr = get_news_addr(addr)) == NULL) {
				fl_set_input(mf_ptr->me_to, "");
				return;
			}
			break;

		case 5:
			if(!strcmp(addr, "!")) {
				mf_ptr->me_flags |= MF_LOCKED;
				folder = choose_folder();
				mf_ptr->me_flags &= ~MF_LOCKED;
				if(folder == NULL)
					return;
			}
			break;

		default:
			return;
			break;
	}

	switch(atype) {
		case 1:
			if(msg->header->To == NULL)
				msg->header->To = ma;
			else {
				adr1 = msg->header->To;
				while(adr1->next_addr != NULL)
					adr1 = adr1->next_addr;
				adr1->next_addr = ma;
			}
			break;

		case 2:
			if(msg->header->Cc == NULL)
				msg->header->Cc = ma;
			else {
				adr1 = msg->header->Cc;
				while(adr1->next_addr != NULL)
					adr1 = adr1->next_addr;
				adr1->next_addr = ma;
			}
			break;

		case 3:
			if(msg->header->Bcc == NULL)
				msg->header->Bcc = ma;
			else {
				adr1 = msg->header->Bcc;
				while(adr1->next_addr != NULL)
					adr1 = adr1->next_addr;
				adr1->next_addr = ma;
			}
			break;

		case 4:
			if(msg->header->News == NULL)
				msg->header->News = naddr;
			else {
				naddr1 = msg->header->News;
				while(naddr1->next != NULL)
					naddr1 = naddr1->next;
				naddr1->next = naddr;
			}
			break;

		case 5:
			if(folder)
				add_fcc_list(msg->header, folder);
			else
				parse_fcc_list(msg->header, addr);
			break;

		default:
			discard_address(ma);
			discard_news_address(naddr);
			break;
	}

	fl_freeze_form(mf_ptr->me_form);
	display_addresses(num);
	fl_set_input(mf_ptr->me_to, "");
	fl_set_object_focus(mf_ptr->me_form, mf_ptr->me_to);
	fl_set_textedit_cursorpos(mf_ptr->me_text, 0, 0, -1, 1);
	fl_unfreeze_form(mf_ptr->me_form);
	mf_ptr->me_flags |= MF_CHANGED;

	return;
}

void cb_addr_list(FL_OBJECT * obj, long num) {
	if(fl_mouse_button() == FL_MIDDLE_MOUSE) {
		if(mf_arr[num]->me_flags & MF_VIEW)
			cb_addr_list_dbl(obj, num);
		else
			cb_addr_modify(obj, num);
	}
}

void cb_addr_list_dbl(FL_OBJECT * obj, long num) {
	int lnum, i;
	struct _mail_addr *ma, *addr;

	lnum = fl_get_browser(obj);
	if((ma = get_msgaddr_byline(num, lnum, &i)) == NULL)
		return;

	if((i == NN_TYPE) || (i == FCC_TYPE))
		return;

	addr = copy_address(ma);
	addr->next_addr = NULL;

	if(display_msg(MSG_QUEST, NULL, "Append to address book?")) {
		add_each_addr(addr, "default");
		save_addressbook("default");
	}

	discard_address(addr);

	return;
}

void cb_addr_modify(FL_OBJECT * obj, long num) {
	struct _mail_addr *adr, *ma;
	struct msg_form *mf_ptr;
	struct _mail_msg *msg;
	int type, oldtype, line;

	mf_ptr = mf_arr[num];
	msg = mf_ptr->me_msg;

	line = fl_get_browser(mf_ptr->me_to_list);

	if((adr = get_msgaddr_byline(num, line, &oldtype)) == NULL)
		return;

	if((oldtype == NN_TYPE) || (oldtype == FCC_TYPE))
		return;

	type = oldtype;
	fl_deactivate_form(mf_ptr->me_form);
	if(mod_addr(adr, &type) == -1) {
		fl_activate_form(mf_ptr->me_form);
		return;
	}

	fl_activate_form(mf_ptr->me_form);
	if(type == oldtype) {
		fl_freeze_form(mf_ptr->me_form);
		display_addresses(num);
		fl_unfreeze_form(mf_ptr->me_form);
		mf_ptr->me_flags |= MF_CHANGED;
		return;
	}

	switch(oldtype) {
		case TO_TYPE:
			if(msg->header->To == adr)
				msg->header->To = adr->next_addr;
			else {
				ma = msg->header->To;
				while(ma->next_addr != adr)
					ma = ma->next_addr;
				ma->next_addr = adr->next_addr;
			}
			break;
		case CC_TYPE:
			if(msg->header->Cc == adr)
				msg->header->Cc = adr->next_addr;
			else {
				ma = msg->header->Cc;
				while(ma->next_addr != adr)
					ma = ma->next_addr;
				ma->next_addr = adr->next_addr;
			}
			break;
		case BCC_TYPE:
			if(msg->header->Bcc == adr)
				msg->header->Bcc = adr->next_addr;
			else {
				ma = msg->header->Bcc;
				while(ma->next_addr != adr)
					ma = ma->next_addr;
				ma->next_addr = adr->next_addr;
			}
			break;
	}

	adr->next_addr = NULL;

	switch(type) {
		case TO_TYPE:
			if(msg->header->To == NULL)
				msg->header->To = adr;
			else {
				ma = msg->header->To;
				while(ma->next_addr != NULL)
					ma = ma->next_addr;
				ma->next_addr = adr;
			}
			break;

		case CC_TYPE:
			if(msg->header->Cc == NULL)
				msg->header->Cc = adr;
			else {
				ma = msg->header->Cc;
				while(ma->next_addr != NULL)
					ma = ma->next_addr;
				ma->next_addr = adr;
			}
			break;

		case BCC_TYPE:
			if(msg->header->Bcc == NULL)
				msg->header->Bcc = adr;
			else {
				ma = msg->header->Bcc;
				while(ma->next_addr != NULL)
					ma = ma->next_addr;
				ma->next_addr = adr;
			}
			break;
	}

	fl_freeze_form(mf_ptr->me_form);
	display_addresses(num);
	fl_select_browser_line(mf_ptr->me_to_list, 1);
	fl_unfreeze_form(mf_ptr->me_form);
	mf_ptr->me_flags |= MF_CHANGED;
	return;
}

void cb_addr_del(FL_OBJECT * obj, long num) {
	struct msg_form *mf_ptr;
	struct _mail_msg *msg;
	struct _mail_addr *adr, *ma;
	struct _news_addr *naddr, *naddr1;
	int line, type;

	mf_ptr = mf_arr[num];
	msg = mf_ptr->me_msg;
	line = fl_get_browser(mf_ptr->me_to_list);
	if((adr = get_msgaddr_byline(num, line, &type)) == NULL)
		return;

	switch(type) {
		case TO_TYPE:
			if(msg->header->To == adr)
				msg->header->To = adr->next_addr;
			else {
				ma = msg->header->To;
				while(ma->next_addr != adr)
					ma = ma->next_addr;
				ma->next_addr = adr->next_addr;
			}
			adr->next_addr = NULL;
			discard_address(adr);
			break;
		case CC_TYPE:
			if(msg->header->Cc == adr)
				msg->header->Cc = adr->next_addr;
			else {
				ma = msg->header->Cc;
				while(ma->next_addr != adr)
					ma = ma->next_addr;
				ma->next_addr = adr->next_addr;
			}
			adr->next_addr = NULL;
			discard_address(adr);
			break;
		case BCC_TYPE:
			if(msg->header->Bcc == adr)
				msg->header->Bcc = adr->next_addr;
			else {
				ma = msg->header->Bcc;
				while(ma->next_addr != adr)
					ma = ma->next_addr;
				ma->next_addr = adr->next_addr;
			}
			adr->next_addr = NULL;
			discard_address(adr);
			break;
		case NN_TYPE:
			naddr = (struct _news_addr *) adr;
			if(msg->header->News == naddr)
				msg->header->News = naddr->next;
			else {
				naddr1 = msg->header->News;
				while(naddr1->next != naddr)
					naddr1 = naddr1->next;
				naddr1->next = naddr->next;
			}
			naddr->next = NULL;
			discard_news_address(naddr);
			break;
		case FCC_TYPE:
			del_fcc_list(msg, (char *) adr);
			break;
	}

	fl_freeze_form(mf_ptr->me_form);
	display_addresses(num);
	fl_select_browser_line(mf_ptr->me_to_list, 1);
	fl_unfreeze_form(mf_ptr->me_form);
	mf_ptr->me_flags |= MF_CHANGED;

	return;
}

void cb_subject_menu(FL_OBJECT * obj, long num) {
	fl_set_input(mf_arr[num]->me_subj, fl_get_menu_text(obj));
}

void cb_from_menu(FL_OBJECT * obj, long num) {
	fl_set_input(mf_arr[num]->me_from, fl_get_menu_text(obj));
}

void cb_msg_help(FL_OBJECT * obj, long num) {
	struct msg_form *mf;
	int n;

	mf = mf_arr[num];

	n = fl_get_menu(obj);
	switch(n) {
		case 1:
			if(mf->me_flags & MF_VIEW)
				helpchapter(10);
			else
				helpchapter(11);
			break;
	}
}

void cb_feelings_menu(FL_OBJECT * obj, long num) {
	char *feeling;

	if(mf_arr[num]->me_flags & MF_READONLY)
		return;

	if(mf_arr[num]->me_flags & MF_LOCKED)
		return;

	feeling = NULL;

	switch(fl_get_menu(obj)) {
		case 1:
			feeling = ":-)";
			break;

		case 2:
			feeling = ":-(";
			break;

		case 3:
			feeling = ";-)";
			break;
	}


	if(feeling)
		fl_insert_textedit(mf_arr[num]->me_text, feeling);
}

void cb_msg_edit(FL_OBJECT * obj, long num) {
	struct msg_form *mf;
	int n;
	u_long offt;
	const char *fname;
	char *tfile;
	UUEncode encode;

	mf = mf_arr[obj->u_ldata];

	n = num < 0 ? abs(num) : fl_get_menu(obj);
	num = obj->u_ldata;

	if(!mf)
		return;

	if(!mf->me_msg)
		return;

	if(mf->me_flags & MF_LOCKED)
		return;

	if(mf->me_flags & MF_READONLY)
		return;

	fl_deactivate_form(mf->me_form);
	set_cursor(mf->me_form, XC_watch);
	mf->me_flags |= MF_CHANGED;

	switch(n) {
		case 1:     /* Insert file */
			fl_set_fselector_title("Choose file to insert");
			if(!(fname = fl_show_file_selector("Insert file", "", "", "")))
				break;

			fl_check_only_forms();
			if((tfile = form_to_msg(num, 0)) == NULL)
				break;
			fl_get_textedit_cursorpos(mf->me_text, NULL, NULL, &offt);
			add_file_to_msg(tfile, (char *) fname, offt, 0);
			update_mime(mf->me_msg);
			update_msg(num);
			break;

		case 2:     /* Uuencode file */
			if(mf->me_msg->mime) {
				if((mf->me_msg->mime->encoding->c_trans_enc == CE_QPRT) ||
				   (mf->me_msg->mime->encoding->c_trans_enc == CE_BASE64))
					display_msg(MSG_WARN, "uuencode",
								"uuencoding is not recommended with BASE64\nor quoted-printable message encoding\nsome e-mail clients may have problems with decoding of this message");
			}
			fl_set_fselector_title("Choose file to uuencode");
			if(!(fname = fl_show_file_selector("Uuencode file", "", "", "")))
				break;

			fl_check_only_forms();
			if((tfile = form_to_msg(num, 0)) == NULL)
				break;

			encode.open(tfile);
			if (!encode.addFile(fname))
				display_msg(MSG_WARN, "uuencode",
					"Can't uuencode %s.", fname);
			encode.close();

			update_mime(mf->me_msg);
			update_msg(num);
			break;

		case 3:     /* Save to file */
			fl_set_fselector_title("Select file to save message text");
			fname = fl_show_file_selector("Save as", "", "", "msg.txt");
			if(!fname || !*fname)
				break;

			compose_msg_text(mf, 1);

			if(save_part(mf->me_msg, get_text_part(mf->me_msg),
						 (char *) fname, 0) == -1)
				display_msg(MSG_WARN, "save", "Can not save message");
			break;

		case 4:     /* Append to file */
			fl_set_fselector_title("Select file to append message text");
			fname = fl_show_file_selector("Append to", "", "", "msg.txt");
			if(!fname || !*fname)
				break;

			compose_msg_text(mf, 1);
			if(save_part(mf->me_msg, get_text_part(mf->me_msg),
						 (char *) fname, SAVEPART_APPEND) == -1)
				display_msg(MSG_WARN, "append", "Can not save message");
			break;

		case 5:     /* Sign Message */
			if((tfile = form_to_msg(num, 0)) == NULL)
				break;
			add_signature_to_msg(mf->me_msg, tfile);
			update_mime(mf->me_msg);
			update_msg(num);
			break;

		case 6:     /* Quote original */
			if((mf->me_msg->data != MSG_DAT_ORIG) ||
			   (mf->me_msg->pdata == NULL)) {
				display_msg(MSG_WARN, "Insert original", "Nothing to insert");
				break;
			}

			if((tfile = form_to_msg(num, 0)) == NULL)
				break;
			fl_get_textedit_cursorpos(mf->me_text, NULL, NULL, &offt);
			insert_orig(tfile, (struct _mail_msg *) mf->me_msg->pdata, 0,
						offt);
			update_mime(mf->me_msg);
			update_msg(num);
			break;

		case 7:     /* run external spellchecker */
			cb_spell_button(NULL, num);
			break;

		default:
			break;
	}

	fl_activate_form(mf->me_form);
	set_cursor(mf->me_form, 0);

}

void set_menu_enc(FL_OBJECT * menu, struct _mime_encoding *encoding) {
	switch(encoding->c_trans_enc) {
		case CE_7BIT:
			fl_set_menu_item_mode(menu, 1, FL_PUP_CHECK);
			fl_set_menu_item_mode(menu, 2, FL_PUP_BOX);
			fl_set_menu_item_mode(menu, 3, FL_PUP_BOX);
			break;

		case CE_8BIT:
			fl_set_menu_item_mode(menu, 1, FL_PUP_BOX);
			fl_set_menu_item_mode(menu, 2, FL_PUP_CHECK);
			fl_set_menu_item_mode(menu, 3, FL_PUP_BOX);
			break;

		case CE_QPRT:
			fl_set_menu_item_mode(menu, 1, FL_PUP_BOX);
			fl_set_menu_item_mode(menu, 2, FL_PUP_BOX);
			fl_set_menu_item_mode(menu, 3, FL_PUP_CHECK);
			break;

		default:
			fl_set_menu_item_mode(menu, 1, FL_PUP_BOX);
			fl_set_menu_item_mode(menu, 2, FL_PUP_BOX);
			fl_set_menu_item_mode(menu, 3, FL_PUP_BOX);
			break;
	}
}

void set_menu_chset(int menu, struct _mime_charset *charset) {
	int k = 0, line = 0;

	while(supp_charsets[k].charset_code != CHAR_UNKNOWN) {
		if(is_charset_alias(supp_charsets[k].charset_name)) {
			k++;
			continue;
		}
		line++;
		if(supp_charsets[k].charset_code == charset->charset_code) {
			fl_setpup_selection(menu, line);
			return;
		}

		k++;
	}
}

void set_msg_chset(struct _mime_charset *charset, int num) {
	struct msg_form *mf;
	struct _mime_msg *mime;
	char buf[255];

	mf = mf_arr[num];
	if(mf->me_flags & MF_LOCKED)
		return;

	fl_freeze_form(mf->me_form);
	fl_set_textedit_fontstyle(mf->me_text,
		charset_style_from_code(charset->charset_code));
	fl_set_textedit_fontsize(mf->me_text,
		charset_size_from_code(charset->charset_code));

	fl_set_browser_fontsize(mf->me_mime, charset_size_from_code(charset->charset_code));
	fl_set_browser_fontstyle(mf->me_mime, charset_style_from_code(charset->charset_code));

	fl_set_object_lstyle(mf->me_subj, charset_style_from_code(charset->charset_code));
	fl_set_object_lstyle(mf->me_from, charset_style_from_code(charset->charset_code));
	fl_set_object_lstyle(mf->me_sender, charset_style_from_code(charset->charset_code));
	fl_unfreeze_form(mf->me_form);

	if(!(mf->me_flags & MF_VIEW)) {
		mime = get_text_part(mf->me_msg);
		if(mime) {
			mime->charset = charset;
			snprintf(buf, sizeof(buf), "%s/%s; charset=%s",
					 mime->mailcap->type_text, mime->mailcap->subtype_text,
					 charset->charset_name);
			replace_mime_field(mime, MIME_C_TYPE, buf);
		}
		mf->me_flags |= MF_CHANGED;
	}
}

void cb_encoding_menu(FL_OBJECT * obj, long num) {
	int i;
	char *mfile;
	struct msg_form *mf;
	struct _mime_msg *mime;

	mf = mf_arr[num];

	if(mf->me_flags & MF_LOCKED)
		return;

	if((i = fl_get_menu(obj)) == 0)
		return;

	if((mf->me_msg->flags & PGP_SIGNED)
	   || (mf->me_msg->flags & PGP_ENCRYPTED)) if(i != 2) {
			display_msg(MSG_WARN, "Encoding",
						"non-8 bit encoding is not recommended with PGP messages");
			i = 2;
		}

	if((mfile = compose_msg_text(mf, 0)) == NULL)
		return;

	if((mime = get_text_part(mf->me_msg)) == NULL) {
		unlink(mfile);
		return;
	}

	switch(i) {
		case 1:
			if(mime->charset->charset_code != US_ASCII)
				display_msg(MSG_WARN, "Encoding",
							"You can use 7 bit encoding only with US-ASCII");
			else
				mime->encoding = &supp_encodings[TEXT_ENCODING];
			break;

		case 2:
			mime->encoding = &supp_encodings[DEFAULT_ENCODING];
			break;

		case 3:
			mime->encoding = &supp_encodings[QPRT_ENCODING];
			break;

		default:
			break;
	}

	mf->me_flags |= MF_CHANGED;
	update_mime(mf->me_msg);
	fl_freeze_form(mf->me_form);
	display_msg_text(mf);
	fl_unfreeze_form(mf->me_form);
}

void cb_lang_menu(FL_OBJECT * obj, long num) {
	int i, k, line;
	struct _mime_charset *chset;

	if((i = fl_get_menu(obj)) == 0)
		return;

	k = 0;
	line = 0;
	chset = NULL;
	while(supp_charsets[k].charset_code != CHAR_UNKNOWN) {
		if(is_charset_alias(supp_charsets[k].charset_name)) {
			k++;
			continue;
		}
		line++;
		if(line == i) {
			chset = &supp_charsets[k];
			break;
		}
		k++;
	}

	if(!chset)
		return;

	set_msg_chset(chset, num);

	return;
}


void cb_pgp_menu(FL_OBJECT * obj, long num) {
	struct msg_form *mf;
	int n;

	mf = mf_arr[num];
	n = fl_get_menu(obj);
	if(!mf || !mf->me_msg)
		return;

	msg_deactivate(num);
	set_cursor(mf->me_form, XC_watch);
	mf->me_flags |= MF_CHANGED;

	switch(n) {
		case 1:     /* PGP sign message */
			cb_pgp_sign_button(NULL, num);
			break;

		case 2:     /* PGP encode message */
			cb_pgp_encode_button(NULL, num);
			break;

		case 3:     /* PGP sign and encode message */
			cb_pgp_signencode_button(NULL, num);
			break;

		case 4:     /* PGP add key */
			cb_pgp_addkey_button(NULL, num);
			break;

		case 5:     /* PGP decode message */
			cb_pgp_decode_button(NULL, num);
			break;

		case 6:     /* PGP verify signature */
			cb_pgp_verify_button(NULL, num);
			break;

		case 7:     /* PGP extract key */
			cb_pgp_extkey_button(NULL, num);
			break;

		default:
			break;
	}

	set_cursor(mf->me_form, 0);
	msg_activate(num);
}

void cb_mime_list(FL_OBJECT * obj, long num) {
	struct msg_form *mf;
	int apup;

	mf = mf_arr[num];
	if(!(mf->me_flags & MF_VIEW))
		return;

	switch(fl_mouse_button()) {
		case FL_RIGHT_MOUSE:
			apup =
			fl_defpup(mf->me_form->window,
					  "Attachment%t|Save%x1|View%x3|View as%x4|Print%x5");
			menuind = fl_dopup(apup);
			cb_mime(NULL, num);
			fl_freepup(apup);
			break;

		case FL_MIDDLE_MOUSE:
			cb_mime_list_dbl(obj, num);
			break;
	}
}

struct _mime_msg *mime_selected(int num) {
	struct _mime_msg *mime;
	struct msg_form *mf;
	int n;

	mf = mf_arr[num];
	n = fl_get_browser(mf->me_mime);
	if(n == 0)
		return NULL;

	mime = mf->me_msg->mime;
	while(n && mime) {
		if(!(mime->flags & ATTACHMENT) || (mime->flags & TEXT_PART)) {
			mime = mime->mime_next;
			continue;
		}
		n--;
		if(!n)
			break;

		mime = mime->mime_next;
	}

	return mime;
}

void cb_mime_list_dbl(FL_OBJECT * obj, long num) {
	struct _mime_msg *mime;
	struct _mail_msg *msg;
	struct msg_form *mf;

	mf = mf_arr[num];
	if(mf->me_flags & MF_LOCKED)
		return;

	msg = mf->me_msg;
	mime = mime_selected(num);

	if(!(mf->me_flags & MF_VIEW) || !mime)
		return;

	msg_deactivate(num);
	set_cursor(mf->me_form, XC_watch);
	view_part(msg, mime);
	set_cursor(mf->me_form, 0);
	msg_activate(num);

	return;
}

int dir_filter(const char *name, int type) {
	return type == FT_DIR;
}

void cb_mime(FL_OBJECT * obj, long num) {
	struct _mime_msg *mime, *mime1;
	struct _mail_msg *msg;
	struct _mime_mailcap *mc, *mcold;
	struct msg_form *mf;
	int n;
	FL_DIRLIST_FILTER of;
	char *file;

	mf = mf_arr[num];
	if(mf->me_flags & MF_LOCKED)
		return;

	msg = mf->me_msg;
	mime = mime_selected(num);

	if(obj == NULL)
		n = menuind;
	else
		n = fl_get_menu(obj);

	if(!mime && (n != 6) && (n != 2))
		return;

	switch(n) {
		case 1:     /* Save attachment */
			fl_deactivate_form(mf->me_form);
			set_cursor(mf->me_form, XC_watch);
			save_part(msg, mime, NULL, 0);
			set_cursor(mf->me_form, 0);
			fl_activate_form(mf->me_form);
			break;

		case 2:     /* Save all attachments */
			fl_deactivate_form(mf->me_form);
			set_cursor(mf->me_form, XC_watch);
			fl_set_fselector_title("Save attachments to");
			of = fl_set_dirlist_filter(dir_filter);
			fl_invalidate_fselector_cache();
			fl_show_fselector("Save to", NULL, NULL, NULL);
			fl_set_dirlist_filter(of);
			fl_invalidate_fselector_cache();
			file = (char *) fl_get_directory();
			if(!file || !*file) {
				set_cursor(mf->me_form, 0);
				fl_activate_form(mf->me_form);
				break;
			}
			mime = msg->mime;
			while(mime) {
				if((mime->flags & ATTACHMENT) && !(mime->flags & TEXT_PART))
					save_part(msg, mime, file, SAVEPART_CHFILE);
				mime = mime->mime_next;
			}
			set_cursor(mf->me_form, 0);
			fl_activate_form(mf->me_form);
			break;

		case 3:     /* View attachment */
			msg_deactivate(num);
			set_cursor(mf->me_form, XC_watch);
			view_part(msg, mime);
			set_cursor(mf->me_form, 0);
			msg_activate(num);
			break;

		case 4:     /* View attachment as */
			msg_deactivate(num);
			set_cursor(mf->me_form, XC_watch);
			if((mc = mcap_select(mime->mailcap->type_text,
								 mime->mailcap->subtype_text)) != NULL) {
				mcold = mime->mailcap;
				mime->mailcap = mc;
				view_part(msg, mime);
				mime->mailcap = mcold;
			}
			set_cursor(mf->me_form, 0);
			msg_activate(num);
			break;

		case 5:     /* Print attachment */
			set_cursor(mf->me_form, XC_watch);
			msg_deactivate(num);
			if(mime->mailcap->print)
				(*mime->mailcap->print) (msg, mime);
			else
				display_msg(MSG_WARN, "Don't know how to print", "%s/%s",
							mime->mailcap->type_text,
							mime->mailcap->subtype_text);
			msg_activate(num);
			set_cursor(mf->me_form, 0);
			break;

		case 6:     /* Add attachment */
			if(mf->me_flags & MF_READONLY)
				break;
			fl_deactivate_form(mf->me_form);
			set_cursor(mf->me_form, XC_watch);
			mime1 = compose_attachment(NULL);
			if(mime1 != NULL) {
				form_to_msg(num, 0);
				fl_check_only_forms();
				mime1->mime_next = msg->mime;
				msg->mime = mime1;
				if(update_mime(msg) == -1)
					display_msg(MSG_WARN, "MIME", "Mime update failed");

				update_msg(num);
			}
			set_cursor(mf->me_form, 0);
			mf->me_flags |= MF_CHANGED;
			fl_activate_form(mf->me_form);
			break;

		case 7:     /* Delete attachment */
			if(mf->me_flags & MF_READONLY)
				break;
			fl_deactivate_form(mf->me_form);
			set_cursor(mf->me_form, XC_watch);
			form_to_msg(num, 0);
			mime->flags &= ~ATTACHMENT;
			update_mime(msg);
			update_msg(num);
			set_cursor(mf->me_form, 0);
			mf->me_flags |= MF_CHANGED;
			fl_activate_form(mf->me_form);
			break;

		case 8:     /* Edit attachment */
			if(mf->me_flags & MF_READONLY)
				break;
			fl_deactivate_form(mf->me_form);
			set_cursor(mf->me_form, XC_watch);
			mime1 = compose_attachment(mime);
			if(mime1 != NULL) {
				form_to_msg(num, 0);
				fl_check_only_forms();
				if(update_mime(msg) == -1)
					display_msg(MSG_WARN, "MIME", "Mime update failed");

				update_msg(num);
			}

			set_cursor(mf->me_form, 0);
			mf->me_flags |= MF_CHANGED;
			fl_activate_form(mf->me_form);
			break;

		default:
			break;

	}
}

void cb_msg_message(FL_OBJECT * obj, long num) {
	struct msg_form *mf;
	int n;
	const char *fname;
	char *sel;
	UUDecode decode;

	mf = mf_arr[num];
	if((mf->me_flags & MF_BUSY) || (mf->me_flags & MF_LOCKED))
		return;

	n = fl_get_menu(obj);
	mf->me_flags |= MF_BUSY;
	switch(n) {
		case 1:     /* Reply to sender */
			msg_deactivate(num);
			mf->me_flags |= MF_LOCKED;
			sel = fl_get_textedit_seltext(mf->me_text);
			edit_msg(get_reply_msg(mf->me_msg, sel, 0));
			if(sel)
				free(sel);
			redraw_fld(outbox);
			redraw_fld_line(mf->me_msg->folder);
			msg_activate(num);
			break;

		case 2:     /* Reply to all */
			msg_deactivate(num);
			mf->me_flags |= MF_LOCKED;
			sel = fl_get_textedit_seltext(mf->me_text);
			edit_msg(get_reply_msg(mf->me_msg, sel, 2));
			if(sel)
				free(sel);
			redraw_fld(outbox);
			redraw_fld_line(mf->me_msg->folder);
			msg_activate(num);
			break;

		case 3:     /* Forward */
			msg_deactivate(num);
			set_cursor(mf->me_form, XC_watch);
			sel = fl_get_textedit_seltext(mf->me_text);
			edit_msg(get_fwd_msg(mf->me_msg, sel));
			if(sel)
				free(sel);
			redraw_fld(outbox);
			set_cursor(mf->me_form, 0);
			msg_activate(num);
			break;

		case 4:
			if(mf->me_flags & MF_LOCKED)
				break;
			msg_deactivate(num);
			mf->me_msg->status &= ~LOCKED;
			mf->me_msg = move_message(mf->me_msg, NULL);
			if(mf->me_msg && !Config.getInt("viewexit", 0)) {
				update_msg(num);
				msg_activate(num);
			} else {
				msg_activate(num);
				end_msg(num);
			}
			break;

		case 5:
			cb_mbutton_delete(NULL, num);
			break;

		case 6:     /* Show header */
			if(mf->me_flags & MF_HEADER) {
				mf->me_flags &= ~MF_HEADER;
				fl_set_menu_item_mode(obj, 6, FL_PUP_BOX);
			} else {
				mf->me_flags |= MF_HEADER;
				fl_set_menu_item_mode(obj, 6, FL_PUP_CHECK);
			}
			fl_freeze_form(mf->me_form);
			display_msg_text(mf);
			fl_unfreeze_form(mf->me_form);
			break;
		case 7:     /* Save from field */
			add_each_addr(mf->me_msg->header->From, "default");
			save_addressbook("default");
			break;

		case 8:     /* Save to file */
			if(!mf->me_msg)
				break;

			fl_set_fselector_title("Select file to save message text");
			fname = fl_show_file_selector("Save as", "", "", "msg.txt");
			if(!fname || !*fname)
				break;
			if(save_part(mf->me_msg, get_text_part(mf->me_msg),
						 (char *) fname, 0) == -1)
				display_msg(MSG_WARN, "save", "Can not save message");
			break;

		case 9:     /* Append to file */
			if(!mf->me_msg)
				break;

			fl_set_fselector_title("Select file to append message text");
			fname = fl_show_file_selector("Append to", "", "", "msg.txt");
			if(!fname || !*fname)
				break;
			if(save_part(mf->me_msg, get_text_part(mf->me_msg),
						 (char *) fname, SAVEPART_APPEND) == -1)
				display_msg(MSG_WARN, "append", "Can not save message");
			break;

		case 10:        /* Uudecode */
			if(!mf->me_msg)
				break;

			decode.open(mf->me_msg);
			while ((fname = decode.getNextFileName()) != NULL) {
				const char *fout;

				fl_set_fselector_title("Save uuencoded part as");
				fout = fl_show_fselector("Save as", "", "", fname);

				if (fout != NULL && !decode.getNextFile(fout))
					display_msg(MSG_WARN, "uudecode",
						"Can't uudecode %s", fout);
			}
		
			break;

		case 11:        /* Save all addresses */
			add_msg_addr(mf->me_msg, "default");
			save_addressbook("default");
			break;

		case 12:        /* Print */
			set_cursor(mf->me_form, XC_watch);
			msg_deactivate(num);
			lpr_message(mf->me_msg);
			msg_activate(num);
			set_cursor(mf->me_form, 0);
			break;

		default:
			break;
	}
	mf->me_flags &= ~MF_BUSY;
}


void cb_msg_file_view(FL_OBJECT * obj, long num) {
	struct msg_form *mf;
	int n;

	mf = mf_arr[num];

	if(mf->me_flags & MF_LOCKED)
		return;

	n = fl_get_menu(obj);
	switch(n) {
		case 1:
			end_msg(num);
	}
}

void cb_msg_file_edit(FL_OBJECT * obj, long num) {
	struct msg_form *mf;
	struct _mail_msg *msg;
	char *tfile;
	int n, qu, oldoffline, oflags;

	mf = mf_arr[num];
	if(mf == NULL)
		return;

	if(mf->me_flags & MF_LOCKED)
		return;

	msg = mf->me_msg;
	if(msg == NULL)
		return;

	qu = 0;
	oldoffline = 0;

	n = fl_get_menu(obj);
	switch(n) {
		case 2:     /* Queue */
			qu = 1;
		case 1:     /* Send */
			if((msg->header->To == NULL) && (msg->header->News == NULL)) {
				display_msg(MSG_WARN, "send",
							"Please specify at least one recipient");
				break;
			}

			if((strlen(fl_get_input(mf->me_subj)) < 1) &&
			   !display_msg(MSG_QUEST | MSG_DEFNO, "send",
							"Empty subject, are you sure?"))
				break;

			if(!(msg->flags & SIGNED) && fl_get_button(mf->me_sign)) {
				if((tfile = form_to_msg(num, 0)) != NULL) {
					add_signature_to_msg(mf->me_msg, tfile);
					update_mime(mf->me_msg);
				}

				if(!(msg->flags & PGP_SIGNED) && fl_get_button(mf->me_pgp)) {
					display_msg_text(mf);
					if(pgp_message(num, SIGN) != 0)
						return;
				}
			} else {
				form_to_msg(num, 1);
				if(!(msg->flags & PGP_SIGNED) && fl_get_button(mf->me_pgp)) {
					if(pgp_message(num, SIGN) != 0)
						return;
				}
			}

			oflags = msg->status;
			msg->status &= ~LOCKED;
			msg->status &= ~MSGNEW;
			release_orig(num);
			msg_deactivate(num);
			set_cursor(mf->me_form, XC_watch);
			if(send_msg(msg, qu) == -1) {
				msg->status |= LOCKED;
				if(oflags & MSGNEW)
					msg->status |= MSGNEW;
				update_msg(num);
				msg_activate(num);
				set_cursor(mf->me_form, 0);
				break;
			}
			set_cursor(mf->me_form, 0);
			msg_activate(num);

			mf_arr[num]->me_msg = NULL;
			end_msg(num);

			break;

		case 3:     /* Exit */
			cb_mbutton_exit_edit(NULL, num);
			break;
	}
}

void cb_attach_button(FL_OBJECT * obj, long num) {
	struct _mime_msg *mime;
	struct _mail_msg *msg;
	struct msg_form *mf;

	mf = mf_arr[num];
	msg = mf->me_msg;

	if(mf->me_flags & MF_READONLY)
		return;
	if(mf->me_flags & MF_LOCKED)
		return;
	fl_deactivate_form(mf->me_form);
	set_cursor(mf->me_form, XC_watch);
	mime = compose_attachment(NULL);
	if(mime != NULL) {
		form_to_msg(num, 0);
		fl_check_only_forms();
		mime->mime_next = msg->mime;
		msg->mime = mime;
		if(update_mime(msg) == -1)
			display_msg(MSG_WARN, "MIME", "Mime update failed");

		update_msg(num);
	}
	set_cursor(mf->me_form, 0);
	mf->me_flags |= MF_CHANGED;
	fl_activate_form(mf->me_form);

	return;
}

void cb_spell_button(FL_OBJECT * obj, long num) {
	if(mf_arr[num]->me_flags & MF_READONLY)
		return;
	if(mf_arr[num]->me_flags & MF_LOCKED)
		return;
	fl_set_textedit_cursorpos(mf_arr[num]->me_text, 0, 0, -1, 0);
	show_spell_checker(mf_arr[num]->me_text, mf_arr[num]->me_form);
	mf_arr[num]->me_flags |= MF_CHANGED;
	return;
}

void cb_mbutton_insorig(FL_OBJECT * obj, long num) {
	char *tfile;
	u_long offt;

	if(mf_arr[num]->me_flags & MF_LOCKED)
		return;
	if(mf_arr[num]->me_flags & MF_READONLY)
		return;
	if((mf_arr[num]->me_msg->data != MSG_DAT_ORIG) ||
	   (mf_arr[num]->me_msg->pdata == NULL)) {
		display_msg(MSG_WARN, "Insert original", "Nothing to insert");
		return;
	}

	if((tfile = form_to_msg(num, 0)) == NULL)
		return;
	msg_deactivate(num);
	fl_get_textedit_cursorpos(mf_arr[num]->me_text, NULL, NULL, &offt);
	if(fl_get_button_numb(obj) == 3)
		insert_orig(tfile, (struct _mail_msg *) mf_arr[num]->me_msg->pdata,
					1, offt);
	else
		insert_orig(tfile, (struct _mail_msg *) mf_arr[num]->me_msg->pdata,
					0, offt);
	update_mime(mf_arr[num]->me_msg);
	update_msg(num);
	mf_arr[num]->me_flags |= MF_CHANGED;
	msg_activate(num);
}

void cb_mbutton_view(FL_OBJECT * obj, long num) {
	if(fl_get_button_numb(obj) == 3)
		ext_view_msg(num, 1);
	else
		ext_view_msg(num, 0);
}

void cb_mbutton_print(FL_OBJECT * obj, long num) {
	if(!mf_arr[num])
		return;

	if(mf_arr[num]->me_flags & MF_LOCKED)
		return;
	set_cursor(mf_arr[num]->me_form, XC_watch);
	msg_deactivate(num);
	lpr_message(mf_arr[num]->me_msg);
	msg_activate(num);
	set_cursor(mf_arr[num]->me_form, 0);
}

void cb_mbutton_edit(FL_OBJECT * obj, long num) {
	if(mf_arr[num]->me_flags & MF_LOCKED)
		return;
	if(fl_get_button_numb(obj) == 3)
		ext_fulledit_msg(num);
	else
		ext_edit_msg(num);
}

int pgp_message(long num, int mode) {
	struct msg_form *mf;
	char *mfile, *action;
	char buf[255], buf1[255];
	struct _mail_msg *msg, *msg1;
	struct _mime_msg *mime;
	struct pgpargs pgpargs;
	FILE *mfd, *pfd;
	int nnum;

	mf = mf_arr[num];
	msg = mf->me_msg;
	mime = NULL;

	init_pgpargs(&pgpargs);
	if(!mf)
		return -1;

	if(mode & (SIGN | ENCODE)) {
		if(msg->flags & PGP_SIGNED) {
			display_msg(MSG_WARN, "PGP", "Already signed");
			return -1;
		}

		if(msg->flags & PGP_ENCRYPTED) {
			display_msg(MSG_WARN, "PGP", "Already encrypted");
			return -1;
		}
	}

	if(Config.getInt("pgpmime", 0) == 2) {
		if(mode & ENCODE) {
			mf->me_flags |= MF_CHANGED;
			if(pgp_encode_rfc2015(msg, mode) == 0) {
				update_msg(num);
				mf->me_flags |= MF_READONLY;
				fl_textedit_readonly(mf->me_text, 1);
			} else {
				update_msg(num);
				mf->me_flags &= ~MF_READONLY;
				fl_textedit_readonly(mf->me_text, 0);
				return -1;
			}
			return 0;
		}

		if(mode & SIGN) {
			mf->me_flags |= MF_CHANGED;
			if(pgp_sign_rfc2015(msg) == 0) {
				update_msg(num);
				mf->me_flags |= MF_READONLY;
				fl_textedit_readonly(mf->me_text, 1);
			} else {
				update_msg(num);
				mf->me_flags &= ~MF_READONLY;
				fl_textedit_readonly(mf->me_text, 0);
				return -1;
			}
			return 0;
		}
	}

	if(mode & ADDKEY) {
		unsigned long id;
		if((mf->me_flags & MF_VIEW) || (mf->me_flags & MF_READONLY))
			return -1;
		id = PGP_Lookup_PGPId("", mf->me_form);
		if(id == 0)
			return -1;
		snprintf(buf1, sizeof(buf1), "0x%08X", (int) id);
		pgpargs.recp = buf1;
		mfile = strdup(get_temp_file("pgptmp"));
		goto startpgp;
	}

	if(mf->me_flags & MF_VIEW) {
		if(!(mode & DECODE) && !(mode & VERIFY) && !(mode & EXTKEY))
			return -1;
		mfile = strdup(get_temp_file("pgptmp"));
		if(save_part(msg, get_text_part(msg), mfile, 0) == -1)
			return -1;
	} else {
		if((mime = get_text_part(msg)) == NULL) {
			if(!(mode & DECODE) && !(mode & VERIFY))
				return -1;

			if((mime = mime_selected(num)) == NULL)
				return 0;

			if(mime->mailcap != &mailcap[PGP_MAILCAP])
				return 0;

			mime->mailcap = &mailcap[DEFAULT_MAILCAP];
			snprintf(buf, sizeof(buf), "%s/%s; charset=%s",
					 mailcap[DEFAULT_MAILCAP].type_text,
					 mailcap[DEFAULT_MAILCAP].subtype_text,
					 supp_charsets[def_charset].charset_name);
			replace_mime_field(mime, MIME_C_TYPE, buf);

			mfile = strdup(get_temp_file("pgptmp"));
			if(save_part(msg, mime, mfile, 0) == -1)
				return -1;
			mime->src_info = strdup(mfile);
			mime->flags |= FILE_TEMP;
			mime->encoding = &supp_encodings[DEFAULT_ENCODING];
			replace_mime_field(mime, MIME_C_ENCR,
							   supp_encodings[DEFAULT_ENCODING].
							   encoding_name);
		} else {
			if(mf->me_flags & MF_READONLY) {
				mf->me_flags &= ~MF_READONLY;
				if((mfile = form_to_msg(num, 0)) == NULL)
					return -1;
				mfile = strdup(mfile);
				mf->me_flags |= MF_READONLY;
			} else {
				if((mfile = form_to_msg(num, 0)) == NULL)
					return -1;
				mfile = strdup(mfile);
			}
			if(mode & (ENCODE | SIGN)) {
				if(mime->encoding->c_trans_enc !=
				   supp_encodings[DEFAULT_ENCODING].c_trans_enc)
					display_msg(MSG_MSG, "PGP",
								"Message text converted from %s to %s",
								mime->encoding->encoding_name,
								supp_encodings[DEFAULT_ENCODING].
								encoding_name);
				mime->encoding = &supp_encodings[DEFAULT_ENCODING];
				replace_mime_field(mime, MIME_C_ENCR,
								   supp_encodings[DEFAULT_ENCODING].
								   encoding_name);
			}
		}
	}

	if((mode & ENCODE) && !(pgpargs.recp = get_pgp_recp(msg))) {
		display_msg(MSG_WARN, "PGP encode",
					"Please specify recipient first");
		update_mime(msg);
		update_msg(num);
		unlink(mfile);
		free(mfile);
		return -1;
	}

	startpgp:
	if(mode & (DECODE | SIGN))
		pgpargs.passphrase = input_passphrase();

	if(pgpargs.recp)
		pgpargs.recp = rem_tr_space(pgpargs.recp);

	pgpargs.msg = msg;
	if(pgp_action(mfile, mode, &pgpargs) != 0) {
		if(pgpargs.passphrase)
			free(pgpargs.passphrase);
		update_mime(msg);
		update_msg(num);
		unlink(mfile);
		free(mfile);
		return -1;
	}

	if(mode & SIGN) {
		msg->flags |= PGP_SIGNED;
		mf->me_flags |= MF_READONLY;
		fl_textedit_readonly(mf->me_text, 1);
	}

	if(mode & ENCODE)
		msg->flags |= PGP_ENCRYPTED;

	if((mode & DECODE) && !(mf->me_flags & MF_VIEW)) {
		msg->flags &= ~PGP_ENCRYPTED;
		msg->flags &= ~PGP_SIGNED;
		mf->me_flags &= ~MF_READONLY;
		fl_textedit_readonly(mf->me_text, 0);
	}

	if((mode & VERIFY) && !(mf->me_flags & MF_VIEW)) {
		msg->flags &= ~PGP_SIGNED;
		mf->me_flags &= ~MF_READONLY;
		fl_textedit_readonly(mf->me_text, 0);
	}

	if(pgpargs.passphrase)
		free(pgpargs.passphrase);

	if(mf->me_flags & MF_VIEW) {
		if(!(mode & DECODE)) {
			unlink(mfile);
			free(mfile);
			return -1;
		}

		if((nnum = get_new_name(ftemp)) == -1) {
			display_msg(MSG_WARN, "PGP", "No space in %s", FTEMP);
			unlink(mfile);
			free(mfile);
			return -1;
		}

		snprintf(buf, sizeof(buf), "%s/%d", ftemp->fold_path, nnum);

		if((mfd = fopen(buf, "w")) == NULL) {
			display_msg(MSG_WARN, "PGP", "Can not open %s", buf);
			unlink(mfile);
			free(mfile);
			return -1;
		}

		print_mime_msg_header(NULL, msg, mfd);
		fputc('\n', mfd);

		if((pfd = fopen(mfile, "r")) == NULL) {
			display_msg(MSG_WARN, "PGP", "Can not open %s", buf);
			unlink(mfile);
			free(mfile);
			fclose(mfd);
			unlink(buf);
			return -1;
		}

		while(fgets(buf1, 255, pfd))
			fputs(buf1, mfd);

		fclose(pfd);
		fclose(mfd);

		if((msg1 = get_message(nnum, ftemp)) == NULL) {
			display_msg(MSG_WARN, "PGP", "Can not parse message");
			unlink(buf);
			unlink(mfile);
			free(mfile);
			return -1;
		}

		msg1->flags |= M_TEMP;
		msg1->data = MSG_DAT_ENCAP;
		msg1->pdata = (void *) msg;
		unlink(mfile);
		free(mfile);

		view_msg(msg1, 1);
	} else {
		if(((mode & ENCODE) || (mode & SIGN)) &&
		   Config.getInt("pgpmime", 0)) {
			if((mode & ENCODE) && (mode & SIGN)) {
				action = "encryptsign";
				strcpy(buf, "encrypted and signed PGP message");
			} else if(mode & ENCODE) {
				action = "encrypt";
				strcpy(buf, "encrypted PGP message");
			} else {
				action = "sign";
				strcpy(buf, "signed PGP message");
			}

			replace_mime_field(mime, MIME_C_DESCR, buf);
			if(mime->c_descr)
				free(mime->c_descr);
			mime->c_descr = strdup(buf);

			snprintf(buf, sizeof(buf), "%s/%s; format=text; x-action=%s",
					 mailcap[PGP_MAILCAP].type_text,
					 mailcap[PGP_MAILCAP].subtype_text, action);
			replace_mime_field(mime, MIME_C_TYPE, buf);
			mime->mailcap = &mailcap[PGP_MAILCAP];
			mime->encoding = &supp_encodings[DEFAULT_ENCODING];
			replace_mime_field(mime, MIME_C_ENCR,
							   mime->encoding->encoding_name);
			mime->flags |= ATTACHMENT;
			mime->flags &= ~TEXT_PART;
		}

		if(mode & ADDKEY) {
			if(Config.getInt("pgpmime", 0) == 1) {
				form_to_msg(num, 0);
				mime = create_mime();

				snprintf(buf, sizeof(buf), "public PGP key of '%-.32s'",
						 pgpargs.recp);
				replace_mime_field(mime, MIME_C_DESCR, buf);
				if(mime->c_descr)
					free(mime->c_descr);
				mime->c_descr = strdup(buf);

				snprintf(buf, sizeof(buf), "%s/%s; format=keys-only",
						 mailcap[PGP_MAILCAP].type_text,
						 mailcap[PGP_MAILCAP].subtype_text);
				replace_mime_field(mime, MIME_C_TYPE, buf);
				mime->mailcap = &mailcap[PGP_MAILCAP];
				mime->encoding = &supp_encodings[DEFAULT_ENCODING];
				replace_mime_field(mime, MIME_C_ENCR,
								   mime->encoding->encoding_name);
				mime->flags |= ATTACHMENT;
				mime->flags &= ~TEXT_PART;
				mime->src_info = strdup(mfile);
				mime->mime_next = msg->mime;
				msg->mime = mime;
			} else if(Config.getInt("pgpmime", 0) == 2) {
				form_to_msg(num, 0);
				mime = create_mime();

				snprintf(buf, sizeof(buf), "public PGP key of '%-.32s'",
						 pgpargs.recp);
				replace_mime_field(mime, MIME_C_DESCR, buf);
				if(mime->c_descr)
					free(mime->c_descr);
				mime->c_descr = strdup(buf);

				snprintf(buf, sizeof(buf), "%s/%s",
						 mailcap[PGPKEYS_MAILCAP].type_text,
						 mailcap[PGPKEYS_MAILCAP].subtype_text);
				replace_mime_field(mime, MIME_C_TYPE, buf);
				mime->mailcap = &mailcap[PGPKEYS_MAILCAP];
				mime->encoding = &supp_encodings[DEFAULT_ENCODING];
				replace_mime_field(mime, MIME_C_ENCR,
								   mime->encoding->encoding_name);
				mime->flags |= ATTACHMENT;
				mime->flags &= ~TEXT_PART;
				mime->src_info = strdup(mfile);
				mime->mime_next = msg->mime;
				msg->mime = mime;
			} else {
				if((action = form_to_msg(num, 0)) == NULL) {
					unlink(mfile);
					free(mfile);
					return -1;
				}

				if((mfd = fopen(action, "a")) == NULL) {
					display_msg(MSG_WARN, "Add Key",
								"Can not append to %s", action);
					unlink(mfile);
					free(mfile);
					return -1;
				}

				fputc('\n', mfd);
				if((pfd = fopen(mfile, "r")) == NULL) {
					display_msg(MSG_WARN, "Add Key", "Can not open to %s",
								mfile);
					unlink(mfile);
					free(mfile);
					return -1;
				}

				while(fgets(buf, 255, pfd))
					fputs(buf, mfd);
				fclose(mfd);
				fclose(pfd);
			}
		}

		update_mime(msg);
		update_msg(num);
		mf->me_flags |= MF_CHANGED;
		unlink(mfile);
		free(mfile);
	}

	return 0;
}

void cb_pgp_sign_button(FL_OBJECT * obj, long num) {
	if(mf_arr[num]->me_flags & MF_LOCKED)
		return;

	form_to_msg(num, 1);
	pgp_message(num, SIGN);
}

void cb_pgp_encode_button(FL_OBJECT * obj, long num) {
	if(mf_arr[num]->me_flags & MF_LOCKED)
		return;

	form_to_msg(num, 1);
	pgp_message(num, ENCODE);
}

void cb_pgp_signencode_button(FL_OBJECT * obj, long num) {
	if(mf_arr[num]->me_flags & MF_LOCKED)
		return;

	form_to_msg(num, 1);
	pgp_message(num, ENCODE | SIGN);
}

void cb_pgp_decode_button(FL_OBJECT * obj, long num) {
	if(mf_arr[num]->me_flags & MF_LOCKED)
		return;

	pgp_message(num, DECODE);
}

void cb_pgp_verify_button(FL_OBJECT * obj, long num) {
	if(mf_arr[num]->me_flags & MF_LOCKED)
		return;

	pgp_message(num, VERIFY);
}

void cb_pgp_extkey_button(FL_OBJECT * obj, long num) {
	if(mf_arr[num]->me_flags & MF_LOCKED)
		return;

	pgp_message(num, EXTKEY);
}

void cb_pgp_addkey_button(FL_OBJECT * obj, long num) {
	if(mf_arr[num]->me_flags & MF_LOCKED)
		return;

	form_to_msg(num, 1);
	pgp_message(num, ADDKEY);
}

void cb_mbutton_sign(FL_OBJECT * obj, long num) {
	char *tfile;

	if(mf_arr[num]->me_flags & MF_LOCKED)
		return;

	if((tfile = form_to_msg(num, 0)) == NULL)
		return;

	if(fl_get_button_numb(obj) == 3)
		signform = mf_arr[num]->me_form;
	else
		signform = NULL;
	add_signature_to_msg(mf_arr[num]->me_msg, tfile);
	signform = NULL;
	update_mime(mf_arr[num]->me_msg);
	update_msg(num);
	mf_arr[num]->me_flags |= MF_CHANGED;
}

void cb_mbutton_insert(FL_OBJECT * obj, long num) {
	const char *fname;
	char *tfile;
	u_long offt;

	if(mf_arr[num]->me_flags & MF_LOCKED)
		return;

	fl_set_fselector_title("Choose file to insert");
	if(!(fname = fl_show_file_selector("Insert file", "", "", "")))
		return;

	fl_check_only_forms();
	if((tfile = form_to_msg(num, 0)) == NULL)
		return;

	fl_get_textedit_cursorpos(mf_arr[num]->me_text, NULL, NULL, &offt);
	if(fl_get_button_numb(obj) == 3)
		add_file_to_msg(tfile, (char *) fname, offt, 1);
	else
		add_file_to_msg(tfile, (char *) fname, offt, 0);
	update_mime(mf_arr[num]->me_msg);
	update_msg(num);
	mf_arr[num]->me_flags |= MF_CHANGED;
}

void cb_mbutton_reply(FL_OBJECT * obj, long num) {
	char *sel;

	if(mf_arr[num]->me_flags & MF_LOCKED)
		return;

	msg_deactivate(num);
	mf_arr[num]->me_flags |= MF_LOCKED;
	sel = fl_get_textedit_seltext(mf_arr[num]->me_text);
	if(fl_get_button_numb(obj) == 3)
		edit_msg(get_reply_msg(mf_arr[num]->me_msg, sel, 0));
	else
		edit_msg(get_reply_msg(mf_arr[num]->me_msg, sel, 1));
	redraw_fld(outbox);
	if(sel)
		free(sel);
	msg_activate(num);
}

void cb_mbutton_forward(FL_OBJECT * obj, long num) {
	char *sel;

	msg_deactivate(num);
	sel = fl_get_textedit_seltext(mf_arr[num]->me_text);
	edit_msg(get_fwd_msg(mf_arr[num]->me_msg, sel));
	redraw_fld(outbox);
	if(sel)
		free(sel);
	msg_activate(num);
}

void cb_mbutton_move(FL_OBJECT * obj, long num) {
	struct _mail_msg *msg;
	struct _mail_folder *fld;

	if(mf_arr[num]->me_flags & MF_LOCKED)
		return;

	release_orig(num);
	if(fl_get_button_numb(obj) == 3) {
		mf_arr[num]->me_msg->status &= ~LOCKED;

		msg_deactivate(num);
		msg = move_message_byrule(mf_arr[num]->me_msg);
		msg_activate(num);

		if(msg != mf_arr[num]->me_msg)
			goto checkmmsg;

		if((fld = pup_choose_folder(mf_arr[num]->me_form)) == NULL)
			return;
	} else
		fld = NULL;

	mf_arr[num]->me_msg->status &= ~LOCKED;

	msg_deactivate(num);
	msg = move_message(mf_arr[num]->me_msg, fld);
	msg_activate(num);

	checkmmsg:
	if(msg)
		msg->status |= LOCKED;

	if(msg == mf_arr[num]->me_msg)
		return;

	mf_arr[num]->me_msg = msg;

	if(mf_arr[num]->me_msg && !Config.getInt("viewexit", 0))
		update_msg(num);
	else
		end_msg(num);

	return;
}


void cb_mbutton_delete(FL_OBJECT * obj, long num) {
	if(mf_arr[num]->me_flags & MF_LOCKED)
		return;

	if(obj && (mf_arr[num]->me_flags & MF_BUSY))
		return;
	mf_arr[num]->me_flags |= MF_BUSY;

	mf_arr[num]->me_msg->status &= ~LOCKED;
	release_orig(num);
	if(mf_arr[num]->me_msg->flags & M_TEMP) {
		msg_deactivate(num);
		trash->move(mf_arr[num]->me_msg, trash);
		msg_activate(num);
		mf_arr[num]->me_msg = NULL;
		redraw_fld(trash);
	} else {
		msg_deactivate(num);
		mf_arr[num]->me_msg = delete_msg(mf_arr[num]->me_msg);
		msg_activate(num);
	}

	if(mf_arr[num]->me_msg && !Config.getInt("viewexit", 0)) {
		update_msg(num);
		mf_arr[num]->me_flags &= ~MF_BUSY;
	} else
		end_msg(num);
}

void cb_mbutton_np(FL_OBJECT * obj, long num) {
	struct _mail_msg *msg;
	int i, mnum = obj->u_ldata;

	if(!mf_arr[mnum])
		return;

	msg = mf_arr[mnum]->me_msg;
	if(!msg)
		return;

	if(mf_arr[mnum]->me_flags & MF_LOCKED)
		return;

	fl_set_object_callback(obj, NULL, num);

	if(mf_arr[mnum]->me_flags & MF_BUSY)
		return;
	mf_arr[mnum]->me_flags |= MF_BUSY;

	msg_deactivate(mnum);
	switch(num) {
		case 1:
			msg = prev_msg(1, msg);
			break;
		case 2:
			msg = prev_msg(0, msg);
			break;
		case 3:
			msg = next_msg(0, msg);
			break;
		case 4:
			msg = next_msg(1, msg);
			break;

	}

	if(msg) {
		release_orig(mnum);
		mf_arr[mnum]->me_msg->status &= ~LOCKED;
		msg->free_text(mf_arr[mnum]->me_msg);
		mf_arr[mnum]->me_msg->update(mf_arr[mnum]->me_msg);

		if(msg->data == MSG_DAT_ENCAP) {
			for(i = 0; i < MAX_MSG_FORMS; i++) {
				if((mf_arr[i] != NULL) &&
				   (mf_arr[i]->me_flags & MF_VIEW) &&
				   (mf_arr[i]->me_msg == (struct _mail_msg *) msg->pdata))
					mf_arr[i]->me_flags |= MF_LOCKED;
			}
		}

		if(mf_arr[mnum]->me_msg->flags & M_TEMP) {
			mf_arr[mnum]->me_msg->flags &= ~M_TEMP;
			mf_arr[mnum]->me_msg->status |= DELPERM;
			mf_arr[mnum]->me_msg->mdelete(mf_arr[mnum]->me_msg);
		}

		redraw_msg(mf_arr[mnum]->me_msg);
		mf_arr[mnum]->me_msg = msg;
		update_msg(mnum);
	}

	fl_set_object_callback(obj, cb_mbutton_np, num);
	msg_activate(mnum);
	mf_arr[mnum]->me_flags &= ~MF_BUSY;
}


void cb_mbutton_exit_view(FL_OBJECT * obj, long num) {
	if(mf_arr[num]->me_flags & MF_LOCKED)
		return;

	fl_set_object_callback(obj, NULL, 0);
	end_msg(num);
}

void cb_mbutton_exit_edit(FL_OBJECT * obj, long num) {
	int res;
	struct _mail_msg *msg;

	if(mf_arr[num] == NULL)
		return;

	if(mf_arr[num]->me_flags & MF_LOCKED)
		return;

	if(obj)
		fl_set_object_callback(obj, NULL, 0);

	msg = mf_arr[num]->me_msg;

	if(fl_get_textedit_bufchanged(mf_arr[num]->me_text))
		mf_arr[num]->me_flags |= MF_CHANGED;

	if(!(msg->status & MSGNEW)) {
		if((mf_arr[num]->me_flags & MF_CHANGED) &&
		   fl_show_question("Save changes?", 1))
			form_to_msg(num, 1);

		end_msg(num);
		redraw_msg(msg);
		return;
	}

	fl_set_choices_shortcut("Yy#y", "Nn#n", "Cc#c");
	if(!(mf_arr[num]->me_flags & MF_CHANGED))
		res = 2;
	else
		res =
		fl_show_choices
		("Changes were made to this message\nDo you want to save as draft?",
		 3, "Yes", "No", "Cancel", 1);

	if(res == 3) {
		if(obj)
			fl_set_object_callback(obj, cb_mbutton_exit_edit, num);
		return;
	}


	msg->status &= ~LOCKED;
	msg->status &= ~MSGNEW;

	if(res == 2) {
		msg->status |= (DELETED | DELPERM);

		end_msg(num);
		redraw_fld(outbox);
		return;
	}

	form_to_msg(num, 1);
	msg->status |= MOVED;

	end_msg(num);
	redraw_fld(outbox);
}

int close_edit_form(FL_FORM * form, void *data) {
	FL_OBJECT *obj = (FL_OBJECT *) data;

	if(!form->deactivated)
		cb_mbutton_exit_edit(obj, obj->u_ldata);

	return FL_IGNORE;
}

int close_view_form(FL_FORM * form, void *data) {
	FL_OBJECT *obj = (FL_OBJECT *) data;

	if(!form->deactivated)
		cb_mbutton_exit_view(obj, obj->u_ldata);

	return FL_IGNORE;
}

void cb_mbutton_send(FL_OBJECT * obj, long num) {
	struct _mail_msg *msg;
	char *tfile;
	int oflags;

	if(mf_arr[num] == NULL)
		return;

	if(mf_arr[num]->me_flags & MF_LOCKED)
		return;

	msg = mf_arr[num]->me_msg;
	if(msg == NULL)
		return;

	if((msg->header->To == NULL) && (msg->header->News == NULL)) {
		display_msg(MSG_WARN, "send",
					"Please specify at least one recipient");
		return;
	}

	if((strlen(fl_get_input(mf_arr[num]->me_subj)) < 1) &&
	   !display_msg(MSG_QUEST | MSG_DEFNO, "send",
					"Empty subject, are you sure?"))
		return;

	if(!(msg->flags & SIGNED) && fl_get_button(mf_arr[num]->me_sign)) {
		if((tfile = form_to_msg(num, 0)) != NULL) {
			add_signature_to_msg(msg, tfile);
			update_mime(msg);
		}
		if(!(msg->flags & PGP_SIGNED) &&
		   fl_get_button(mf_arr[num]->me_pgp)) {
			display_msg_text(mf_arr[num]);
			if(pgp_message(num, SIGN) != 0)
				return;
		}
	} else {
		form_to_msg(num, 1);
		if(!(msg->flags & PGP_SIGNED) &&
		   fl_get_button(mf_arr[num]->me_pgp))
			if(pgp_message(num, SIGN) != 0)
				return;
	}

	oflags = msg->status;
	msg->status &= ~LOCKED;
	msg->status &= ~MSGNEW;

	release_orig(num);

	set_cursor(mf_arr[num]->me_form, XC_watch);
	msg_deactivate(num);
	if(send_msg(msg, 0) == -1) {
		msg->status |= LOCKED;
		if(oflags & MSGNEW)
			msg->status |= MSGNEW;
		update_msg(num);
		msg_activate(num);
		set_cursor(mf_arr[num]->me_form, 0);
		return;
	}
	set_cursor(mf_arr[num]->me_form, 0);
	msg_activate(num);

	mf_arr[num]->me_msg = NULL;
	end_msg(num);
}

int cb_pgupdown(FL_FORM * form, void *event) {
	XEvent *xev;
	int i;

	xev = (XEvent *) event;
	if(xev->type != KeyPress)
		return 0;

	for(i = 0; i < MAX_MSG_FORMS; i++) {
		if((mf_arr[i] != NULL) && (mf_arr[i]->me_form == form))
			break;
	}

	if(mf_arr[i] == NULL)
		return 0;

	switch(XKeycodeToKeysym(fl_display, xev->xkey.keycode, 0)) {
		case XK_Next:
			fl_scroll_textedit(mf_arr[i]->me_text, FL_TEXTEDITSCROLL_PGDOWN);
			return 1;
			break;

		case XK_Prior:
			fl_scroll_textedit(mf_arr[i]->me_text, FL_TEXTEDITSCROLL_PGUP);
			return 1;
			break;
	}

	return 0;
}

int
cb_mime_separator(FL_OBJECT * obj, int event, FL_Coord mx, FL_Coord my,
				  int key, void *xev) {
	static int oldy = 0;
	FL_OBJECT *textobj = ((struct msg_form *) obj->u_vdata)->me_text;
	FL_OBJECT *mimeobj = ((struct msg_form *) obj->u_vdata)->me_mime;
	FL_OBJECT *hsbrobj;
	int hsbrwidth;

	switch(event) {
		case FL_PUSH:
			if(key != 1)
				return 0;
			fl_drawmode(GXxor);
			fl_rectf(obj->x, obj->y, obj->w, obj->h, FL_WHITE);
			fl_drawmode(GXcopy);
			oldy = obj->y;
			break;

		case FL_RELEASE:
			if((key != 1) && (key != 0))
				return 0;
			hsbrobj = fl_get_textedit_hscrollbar(textobj);
			hsbrwidth = hsbrobj ? hsbrobj->h : 0;
			if(my <= (textobj->y + hsbrwidth + 10))
				my = textobj->y + hsbrwidth + 11;
			if(my >= (mimeobj->y + mimeobj->h - 10))
				my = mimeobj->y + mimeobj->h - 11;
			fl_set_object_geometry(mimeobj, mimeobj->x, my + 2, mimeobj->w,
								   (mimeobj->h + mimeobj->y - my - 2));
			fl_set_object_position(obj, obj->x, my);
			fl_set_object_size(textobj, textobj->w,
							   my - textobj->y - hsbrwidth);
			set_cursor(obj->form, 0);
			oldy = 0;
			break;

		case FL_MOUSE:
			if(key != 1)
				return 0;
			hsbrobj = fl_get_textedit_hscrollbar(textobj);
			hsbrwidth = hsbrobj ? hsbrobj->h : 0;
			if(oldy != my) {
				if((my > textobj->y + hsbrwidth + 10) &&
				   (my < (mimeobj->y + mimeobj->h - 10))) {
					fl_drawmode(GXxor);
					fl_rectf(obj->x, oldy, obj->w, 2, FL_WHITE);
					fl_rectf(obj->x, my, obj->w, 2, FL_WHITE);
					fl_drawmode(GXcopy);
					oldy = my;
				}
			}
			break;

		case FL_ENTER:
			set_cursor(obj->form, XC_sb_v_double_arrow);
			break;

		case FL_LEAVE:
			set_cursor(obj->form, 0);
			break;
	}
	return 0;
}

struct msg_form *create_msg_form(struct msg_form *msg_f, int num) {
	FL_FORM *form;
	FL_OBJECT *obj, *fobj = NULL, *sobj = NULL;
	int menubox_bottom = 3;
	int menus_y_offset = menubox_bottom;
	int buttons_y_bottom = menubox_bottom + 25;
	int box_y_bottom = buttons_y_bottom + 50;
	int box_y_height = 116;
	int browserbottom = 200;
	int browserheight = 335;
	int k, lpup;
	char chdescr[41], buf[255];
	XWMHints *xwmh;
	struct _mail_addr *addr, *addr1;
	struct _head_field *hf;

	form = fl_bgn_form(FL_NO_BOX, 805, 605);
	msg_f->me_form = form;

	obj = fl_add_box(FL_FLAT_BOX, 0, 0, 805, 605, "");
	obj->u_ldata = num;

	obj = fl_add_frame(FL_UP_FRAME, 3, menubox_bottom, 799, 20, "");
	obj->u_ldata = num;
	fl_set_object_resize(obj, FL_RESIZE_X);
	fl_set_object_gravity(obj, NorthWestGravity, 0);

	obj = fl_add_menu(FL_PULLDOWN_MENU, 3, menus_y_offset, 30, 20, "File");
	obj->u_ldata = num;
	fl_set_object_boxtype(obj, FL_FLAT_BOX);
	fl_set_object_lalign(obj, FL_ALIGN_LEFT);
	fl_set_object_resize(obj, FL_RESIZE_NONE);
	fl_set_object_gravity(obj, NorthWestGravity, 0);
	fl_set_object_shortcut(obj, "#E", 1);

	if(msg_f->me_flags & MF_VIEW) {
		fl_set_menu(obj, "Exit (Alt+X)");
		fl_set_object_callback(obj, cb_msg_file_view, num);
		fl_set_menu_item_shortcut(obj, 1, "Xx#x");
	} else {
		fl_set_menu(obj, "Send (Alt+S)|Queue|Exit (Alt+X)");
		fl_set_object_callback(obj, cb_msg_file_edit, num);
		fl_set_menu_item_shortcut(obj, 1, "Ss#s");
		fl_set_menu_item_shortcut(obj, 2, "Qq#q");
		fl_set_menu_item_shortcut(obj, 3, "Xx#x");
	}

	obj =
	fl_add_menu(FL_PULLDOWN_MENU, 755, menus_y_offset, 40, 20, "Help");
	obj->u_ldata = num;
	fl_set_object_boxtype(obj, FL_FLAT_BOX);
	fl_set_object_lalign(obj, FL_ALIGN_RIGHT);
	fl_set_menu(obj, "Contents");
	fl_set_menu_item_shortcut(obj, 1, "Cc#c");
	fl_set_object_callback(obj, cb_msg_help, num);
	fl_set_object_resize(obj, FL_RESIZE_NONE);
	fl_set_object_gravity(obj, NorthGravity, EastGravity);

	obj =
	fl_add_menu(FL_PULLDOWN_MENU, 160, menus_y_offset, 80, 20,
				"Attachment");
	obj->u_ldata = num;
	fl_set_object_boxtype(obj, FL_FLAT_BOX);
	fl_set_object_lalign(obj, FL_ALIGN_LEFT);
	fl_set_object_callback(obj, cb_mime, num);
	fl_set_object_resize(obj, FL_RESIZE_NONE);
	fl_set_object_gravity(obj, NorthWestGravity, 0);
	fl_set_object_shortcut(obj, "#C", 1);

	if(msg_f->me_flags & MF_VIEW) {
		fl_set_menu(obj, "Save|Save All|View|View As|Print");
		fl_set_menu_item_shortcut(obj, 1, "Ss#s");
		fl_set_menu_item_shortcut(obj, 2, "Aa#a");
		fl_set_menu_item_shortcut(obj, 3, "Vv#v");
		fl_set_menu_item_shortcut(obj, 4, "Ww#w");
		fl_set_menu_item_shortcut(obj, 5, "Pp#p");

		obj =
		fl_add_menu(FL_PULLDOWN_MENU, 80, menus_y_offset, 70, 20,
					"Message");
		obj->u_ldata = num;
		fl_set_object_boxtype(obj, FL_FLAT_BOX);
		fl_set_object_lalign(obj, FL_ALIGN_LEFT);
		fl_set_object_resize(obj, FL_RESIZE_NONE);
		fl_set_object_gravity(obj, NorthWestGravity, 0);
		fl_set_object_shortcut(obj, "#S", 1);
		fl_set_menu(obj,
					"Reply to Sender|Reply to All (Alt+R)|Forward (Alt+F)%l|Move to Folder (Alt+M)|Delete (Alt+D)%l|Show Header|Save From Field%l|Save to File|Append to File|Uudecode|Save All Addr|Print");
		fl_set_menu_item_shortcut(obj, 1, "Tt#t");
		fl_set_menu_item_shortcut(obj, 2, "Rr#r");
		fl_set_menu_item_shortcut(obj, 3, "Ff#f");
		fl_set_menu_item_shortcut(obj, 4, "Mm#m");
		fl_set_menu_item_shortcut(obj, 5, "Dd#d");
		fl_set_menu_item_shortcut(obj, 6, "Hh#h");
		fl_set_menu_item_shortcut(obj, 7, "Ll#l");
		fl_set_menu_item_shortcut(obj, 8, "Ss#s");
		fl_set_menu_item_shortcut(obj, 9, "Aa#a");
		fl_set_menu_item_shortcut(obj, 10, "Uu#u");
		fl_set_menu_item_shortcut(obj, 11, "Vv#v");
		fl_set_menu_item_shortcut(obj, 12, "Pp#p");

		if(Config.getInt("sheader", 0))
			fl_set_menu_item_mode(obj, 6, FL_PUP_CHECK);
		else
			fl_set_menu_item_mode(obj, 6, FL_PUP_BOX);

		fl_set_object_callback(obj, cb_msg_message, num);

		obj =
		fl_add_menu(FL_PULLDOWN_MENU, 240, menus_y_offset, 60, 20,
					"PGP");
		obj->u_ldata = num;
		fl_set_object_shortcut(obj, "#G", 1);
		fl_set_object_boxtype(obj, FL_FLAT_BOX);
		fl_set_object_lalign(obj, FL_ALIGN_LEFT);
		fl_set_object_resize(obj, FL_RESIZE_NONE);
		fl_set_object_gravity(obj, NorthWestGravity, 0);
		fl_set_menu(obj, "Decode%x5|Verify%x6|Extract key%x7");
		fl_set_object_callback(obj, cb_pgp_menu, num);

		fl_set_menu_item_shortcut(obj, 1, "Dd#d");
		fl_set_menu_item_shortcut(obj, 2, "Vv#v");
		fl_set_menu_item_shortcut(obj, 3, "Ee#e");

	} else {
		fl_set_menu(obj, "Add (Alt+T) %x6|Delete %x7|Edit %x8");
		fl_set_menu_item_shortcut(obj, 1, "Aa#a");
		fl_set_menu_item_shortcut(obj, 2, "Dd#d");
		fl_set_menu_item_shortcut(obj, 3, "Ee#e");

		obj =
		fl_add_menu(FL_PULLDOWN_MENU, 80, menus_y_offset, 60, 20,
					"Edit");
		obj->u_ldata = num;
		fl_set_object_boxtype(obj, FL_FLAT_BOX);
		fl_set_object_lalign(obj, FL_ALIGN_LEFT);
		fl_set_object_resize(obj, FL_RESIZE_NONE);
		fl_set_object_gravity(obj, NorthWestGravity, 0);
		fl_set_object_shortcut(obj, "#D", 1);
		fl_set_menu(obj, EDIT_MENU);
		fl_set_object_callback(obj, cb_msg_edit, num);

		fl_set_menu_item_shortcut(obj, 1, "Ii#i");
		fl_set_menu_item_shortcut(obj, 2, "Uu#u");
		fl_set_menu_item_shortcut(obj, 3, "Ss#s");
		fl_set_menu_item_shortcut(obj, 4, "Aa#a");
		fl_set_menu_item_shortcut(obj, 5, "Ss#s");
		fl_set_menu_item_shortcut(obj, 6, "Qq#q");
		fl_set_menu_item_shortcut(obj, 6, "Pp#p");

		obj =
		fl_add_menu(FL_PULLDOWN_MENU, 240, menus_y_offset, 60, 20,
					"PGP");
		obj->u_ldata = num;
		fl_set_object_shortcut(obj, "#G", 1);
		fl_set_object_boxtype(obj, FL_FLAT_BOX);
		fl_set_object_lalign(obj, FL_ALIGN_LEFT);
		fl_set_object_resize(obj, FL_RESIZE_NONE);
		fl_set_object_gravity(obj, NorthWestGravity, 0);
		fl_set_menu(obj,
					"Sign|Encode|Sign and Encode|Add Key|Decode|Verify");
		fl_set_object_callback(obj, cb_pgp_menu, num);

		fl_set_menu_item_shortcut(obj, 1, "Ss#s");
		fl_set_menu_item_shortcut(obj, 2, "Ee#e");
		fl_set_menu_item_shortcut(obj, 3, "Nn#n");
		fl_set_menu_item_shortcut(obj, 4, "Aa#a");
		fl_set_menu_item_shortcut(obj, 5, "Dd#d");
		fl_set_menu_item_shortcut(obj, 6, "Vv#v");

		msg_f->me_enc = obj =
						fl_add_menu(FL_PULLDOWN_MENU, 400, menus_y_offset, 70, 20,
									"Encoding");
		obj->u_ldata = num;
		fl_set_object_shortcut(obj, "#O", 1);
		fl_set_object_boxtype(obj, FL_FLAT_BOX);
		fl_set_object_lalign(obj, FL_ALIGN_LEFT);
		fl_set_object_resize(obj, FL_RESIZE_NONE);
		fl_set_object_gravity(obj, NorthWestGravity, 0);
		fl_set_menu(obj, "7 bit%r2|8 bit%r2|Quoted-Printable%r2");
		fl_set_object_callback(obj, cb_encoding_menu, num);

		fl_set_menu_item_shortcut(obj, 1, "7#7");
		fl_set_menu_item_shortcut(obj, 2, "8#8");
		fl_set_menu_item_shortcut(obj, 3, "Qq#q");

		obj =
		fl_add_menu(FL_PULLDOWN_MENU, 480, menus_y_offset, 70, 20,
					"Feelings");
		obj->u_ldata = num;
		fl_set_object_shortcut(obj, "#F", 1);
		fl_set_object_boxtype(obj, FL_FLAT_BOX);
		fl_set_object_lalign(obj, FL_ALIGN_LEFT);
		fl_set_object_resize(obj, FL_RESIZE_NONE);
		fl_set_object_gravity(obj, NorthWestGravity, 0);
		fl_set_menu(obj, "Happy|Sad|Wink");
		fl_set_object_callback(obj, cb_feelings_menu, num);

		fl_set_menu_item_shortcut(obj, 1, "Hh#h");
		fl_set_menu_item_shortcut(obj, 2, "Ss#s");
		fl_set_menu_item_shortcut(obj, 3, "Ww#w");
	}

	obj = fl_add_menu(FL_PULLDOWN_MENU, 320, menus_y_offset, 70, 20, "Language");
	obj->u_ldata = num;
	fl_set_object_shortcut(obj, "#L", 1);
	fl_set_object_boxtype(obj, FL_FLAT_BOX);
	fl_set_object_lalign(obj, FL_ALIGN_LEFT);
	fl_set_object_resize(obj, FL_RESIZE_NONE);
	fl_set_object_gravity(obj, NorthWestGravity, 0);
	fl_set_object_callback(obj, cb_lang_menu, num);
	k = 0;
	lpup = fl_newpup(0);
	msg_f->me_lang = lpup;
	while(supp_charsets[k].charset_code != CHAR_UNKNOWN) {
		if(is_charset_alias(supp_charsets[k].charset_name)) {
			k++;
			continue;
		}

		snprintf(chdescr, sizeof(chdescr), "%s (%s)%%r1",
				 supp_charsets[k].charset_name,
				 supp_charsets[k].charset_descr);
		fl_addtopup(lpup, chdescr);
		k++;
	}
	fl_setpup_shadow(lpup, 0);
	fl_setpup_softedge(lpup, 0);

	fl_set_menu_popup(obj, lpup);

	obj = fl_add_frame(FL_EMBOSSED_FRAME, 3, box_y_bottom, 799, box_y_height, "");
	obj->u_ldata = num;
	fl_set_object_resize(obj, FL_RESIZE_X);
	fl_set_object_gravity(obj, NorthWestGravity, EastGravity);

	obj = fl_add_input(FL_NORMAL_INPUT, 61, box_y_bottom + 2, 369, 28, "");
	fl_set_object_resize(obj, FL_RESIZE_NONE);
	fl_set_object_gravity(obj, NorthWestGravity, 0);
	obj->u_ldata = num;
	msg_f->me_from = obj;
	fl_set_object_callback(obj, cb_txtedit, num);

	msg_f->me_subj = obj =
					 fl_add_input(FL_NORMAL_INPUT, 61, box_y_bottom + 30, 369, 28, "");
	fl_set_object_resize(obj, FL_RESIZE_NONE);
	fl_set_object_gravity(obj, NorthWestGravity, 0);
	obj->u_ldata = num;
	fl_set_object_callback(obj, cb_subjedit, num);

	if(msg_f->me_flags & MF_VIEW) {
		obj =
		fl_add_text(FL_NORMAL_TEXT, 6, box_y_bottom + 35, 50, 18,
					"Subject:");
		obj->u_ldata = num;
		fl_set_object_resize(obj, FL_RESIZE_NONE);
		fl_set_object_gravity(obj, NorthWestGravity, 0);
		fl_set_object_boxtype(obj, FL_FLAT_BOX);
		fl_set_object_lalign(obj, FL_ALIGN_RIGHT);

		obj =
		fl_add_text(FL_NORMAL_TEXT, 6, box_y_bottom + 7, 50, 18,
					"From:");
		obj->u_ldata = num;
		fl_set_object_resize(obj, FL_RESIZE_NONE);
		fl_set_object_gravity(obj, NorthWestGravity, 0);
		fl_set_object_boxtype(obj, FL_FLAT_BOX);
		fl_set_object_lalign(obj, FL_ALIGN_RIGHT);

		obj =
		fl_add_text(FL_NORMAL_TEXT, 6, box_y_bottom + 63, 50, 18,
					"Sender:");
		obj->u_ldata = num;
		fl_set_object_resize(obj, FL_RESIZE_NONE);
		fl_set_object_gravity(obj, NorthWestGravity, 0);
		fl_set_object_boxtype(obj, FL_FLAT_BOX);
		fl_set_object_lalign(obj, FL_ALIGN_RIGHT);

		obj =
		fl_add_input(FL_NORMAL_INPUT, 61, box_y_bottom + 58, 369, 28,
					 "");
		fl_set_object_resize(obj, FL_RESIZE_NONE);
		fl_set_object_gravity(obj, NorthWestGravity, 0);
		obj->u_ldata = num;
		msg_f->me_to = obj;
		fl_set_object_callback(obj, cb_txtedit, num);

		obj =
		fl_add_browser(FL_HOLD_BROWSER, 433, box_y_bottom + 2, 364,
					   112, "");
		fl_set_object_resize(obj, FL_RESIZE_X);
		fl_set_object_gravity(obj, NorthWestGravity, EastGravity);
		obj->u_ldata = num;
		fl_set_object_callback(obj, cb_addr_list, num);
		fl_set_browser_dblclick_callback(obj, cb_addr_list_dbl, num);
		msg_f->me_to_list = obj;

		obj =
		fl_add_text(FL_NORMAL_TEXT, 6, box_y_bottom + 90, 50, 20,
					"Date:");
		obj->u_ldata = num;
		fl_set_object_lalign(obj, FL_ALIGN_RIGHT);
		fl_set_object_boxtype(obj, FL_FLAT_BOX);
		fl_set_object_resize(obj, FL_RESIZE_NONE);
		fl_set_object_gravity(obj, NorthWestGravity, 0);

		obj =
		fl_add_text(FL_NORMAL_TEXT, 61, box_y_bottom + 90, 369, 20,
					"");
		obj->u_ldata = num;
		fl_set_object_resize(obj, FL_RESIZE_NONE);
		fl_set_object_gravity(obj, NorthWestGravity, 0);
		fl_set_object_boxtype(obj, FL_FLAT_BOX);
		msg_f->me_date = obj;
	} else {
		fobj = obj =
			   fl_add_menu(FL_PULLDOWN_MENU, 11, box_y_bottom + 2, 50, 28,
						   "From");
		obj->u_ldata = num;
		fl_set_object_resize(obj, FL_RESIZE_NONE);
		fl_set_object_gravity(obj, NorthWestGravity, 0);
		fl_set_object_boxtype(obj, FL_UP_BOX);
		fl_set_object_lalign(obj, FL_ALIGN_RIGHT);
		fl_set_object_lstyle(obj, FL_NORMAL_STYLE);
		fl_set_object_callback(obj, cb_from_menu, num);

		sobj = obj =
			   fl_add_menu(FL_PULLDOWN_MENU, 11, box_y_bottom + 30, 50, 28,
						   "Subject");
		obj->u_ldata = num;
		fl_set_object_resize(obj, FL_RESIZE_NONE);
		fl_set_object_gravity(obj, NorthWestGravity, 0);
		fl_set_object_boxtype(obj, FL_UP_BOX);
		fl_set_object_lalign(obj, FL_ALIGN_RIGHT);
		fl_set_object_lstyle(obj, FL_NORMAL_STYLE);
		fl_set_object_callback(obj, cb_subject_menu, num);

		obj =
		fl_add_choice(FL_NORMAL_CHOICE, 11, box_y_bottom + 58, 50, 28,
					  "");
		fl_set_object_boxtype(obj, FL_UP_BOX);
		fl_set_object_lstyle(obj, FL_BOLD_STYLE);
		fl_set_object_resize(obj, FL_RESIZE_NONE);
		fl_set_object_gravity(obj, NorthWestGravity, 0);
		fl_set_choice_align(obj, FL_ALIGN_RIGHT);
		obj->u_ldata = num;
		msg_f->me_to_type = obj;

		obj =
		fl_add_input(FL_NORMAL_INPUT, 61, box_y_bottom + 58, 369, 28,
					 "");
		fl_set_object_resize(obj, FL_RESIZE_NONE);
		fl_set_object_gravity(obj, NorthWestGravity, 0);
		obj->u_ldata = num;
		fl_set_object_callback(obj, cb_addr_addto, num);
		fl_set_input_return(obj, FL_RETURN_END);
		fl_set_object_lsize(obj,
							Config.getInt("EditFSize", FL_DEFAULT_SIZE));
		fl_set_object_lstyle(obj,
							 Config.getInt("EditFStyle", FL_NORMAL_SIZE));
		msg_f->me_to = obj;

		obj =
		fl_add_checkbutton(FL_PUSH_BUTTON, 20, box_y_bottom + 92, 20,
						   20, "Confirm\nDelivery");
		fl_set_object_lalign(obj, FL_ALIGN_RIGHT);
		fl_set_object_resize(obj, FL_RESIZE_NONE);
		fl_set_object_gravity(obj, NorthWestGravity, 0);
		obj->u_ldata = num;
		fl_set_object_callback(obj, cb_conf_delivery, num);

		obj =
		fl_add_checkbutton(FL_PUSH_BUTTON, 90, box_y_bottom + 92, 20,
						   20, "Confirm\nReading");
		fl_set_object_lalign(obj, FL_ALIGN_RIGHT);
		fl_set_object_resize(obj, FL_RESIZE_NONE);
		fl_set_object_gravity(obj, NorthWestGravity, 0);
		obj->u_ldata = num;
		fl_set_object_callback(obj, cb_conf_read, num);

		msg_f->me_sign = obj =
						 fl_add_checkbutton(FL_PUSH_BUTTON, 160, box_y_bottom + 92, 20,
											20, "Auto\nSign");
		fl_set_object_lalign(obj, FL_ALIGN_RIGHT);
		fl_set_object_resize(obj, FL_RESIZE_NONE);
		fl_set_object_gravity(obj, NorthWestGravity, 0);
		obj->u_ldata = num;
		fl_set_object_callback(obj, cb_sign, num);

		msg_f->me_pgp = obj =
						fl_add_checkbutton(FL_PUSH_BUTTON, 230, box_y_bottom + 92, 20,
										   20, "PGP\nsign");
		fl_set_object_lalign(obj, FL_ALIGN_RIGHT);
		fl_set_object_resize(obj, FL_RESIZE_NONE);
		fl_set_object_gravity(obj, NorthWestGravity, 0);
		obj->u_ldata = num;
		fl_set_object_callback(obj, cb_pgpsign, num);

		msg_f->me_prior = obj =
						  fl_add_choice(FL_NORMAL_CHOICE, 330, box_y_bottom + 92, 50, 20,
										"Priority:");
		fl_set_object_boxtype(obj, FL_UP_BOX);
		fl_set_object_lalign(obj, FL_ALIGN_LEFT);
		fl_set_object_resize(obj, FL_RESIZE_NONE);
		fl_set_object_gravity(obj, NorthWestGravity, 0);
		obj->u_ldata = num;
		fl_set_object_callback(obj, cb_urgent, num);

		obj =
		fl_add_browser(FL_HOLD_BROWSER, 433, box_y_bottom + 2, 364, 84,
					   "");
		fl_set_object_resize(obj, FL_RESIZE_X);
		fl_set_object_gravity(obj, NorthWestGravity, EastGravity);
		obj->u_ldata = num;
		fl_set_object_callback(obj, cb_addr_list, num);
		fl_set_browser_dblclick_callback(obj, cb_addr_modify, num);
		msg_f->me_to_list = obj;

		obj =
		fl_add_button(FL_NORMAL_BUTTON, 433, box_y_bottom + 88, 90, 25,
					  "Address");
		fl_set_object_resize(obj, FL_RESIZE_X);
		fl_set_object_gravity(obj, NorthWestGravity, 0);
		obj->u_ldata = num;
		fl_set_object_callback(obj, cb_addr_add, num);
		fl_set_button_shortcut(obj, "#A", 0);

		/*
			obj = fl_add_button(FL_NORMAL_BUTTON,535,box_y_bottom+88,165,25,"Modify");
				fl_set_object_resize(obj,FL_RESIZE_X);
			fl_set_object_gravity(obj,NorthWestGravity,EastGravity);
			obj->u_ldata = num;
				fl_set_object_callback(obj,cb_addr_modify,num);
		*/

		obj =
		fl_add_button(FL_NORMAL_BUTTON, 707, box_y_bottom + 88, 90, 25,
					  "Delete");
		fl_set_object_resize(obj, FL_RESIZE_X);
		fl_set_object_gravity(obj, NorthGravity, NorthEastGravity);
		obj->u_ldata = num;
		fl_set_object_callback(obj, cb_addr_del, num);
	}

	obj =
	fl_add_bitmap(FL_NORMAL_BITMAP, 752, menubox_bottom + 23, 50, 50,
				  "");
	fl_set_object_boxtype(obj, FL_FLAT_BOX);
	fl_set_object_resize(obj, FL_RESIZE_NONE);
	fl_set_object_gravity(obj, NorthEastGravity, 0);
	fl_set_object_color(obj, FL_WHITE, FL_WHITE);
	obj->u_ldata = num;
	msg_f->me_bitmap = obj;

	obj =
	fl_add_pixmap(FL_NORMAL_PIXMAP, 752, menubox_bottom + 23, 50, 50,
				  "");
	fl_set_object_boxtype(obj, FL_FLAT_BOX);
	fl_set_object_resize(obj, FL_RESIZE_NONE);
	fl_set_object_gravity(obj, NorthEastGravity, 0);
	fl_set_object_color(obj, FL_WHITE, FL_WHITE);
	obj->u_ldata = num;
	msg_f->me_pixmap = obj;

	obj =
	fl_add_browser(FL_HOLD_BROWSER, 3,
				   browserbottom + browserheight + 32, 799, 35, "");
	fl_set_object_resize(obj, FL_RESIZE_X);
	fl_set_object_gravity(obj, SouthWestGravity, SouthEastGravity);
	fl_set_object_color(obj,
						Config.getInt("ViewBgCol", FL_MCOL),
						FL_YELLOW);
	fl_set_object_lcol(obj,
					   Config.getInt("ViewFgCol", FL_BLACK));
	fl_set_browser_hscrollbar(obj, FL_OFF);
	msg_f->me_mime = obj;
	obj->u_ldata = num;
	fl_set_object_callback(obj, cb_mime_list, num);
	fl_set_browser_dblclick_callback(obj, cb_mime_list_dbl, num);

	if(msg_f->me_flags & MF_VIEW) {
		obj =
		fl_add_textedit(FL_NORMAL_TEXTEDIT, 3, browserbottom, 799,
						browserheight + 30, "");
		fl_set_object_resize(obj, FL_RESIZE_ALL);
		fl_set_object_gravity(obj, NorthWestGravity, SouthEastGravity);
		fl_set_textedit_color(obj,
							  Config.getInt("ViewBgCol", FL_MCOL),
							  Config.getInt("ViewFgCol", FL_BLACK), FL_BLUE, 0);
		fl_set_textedit_wrap(obj,
							 -abs(Config.getInt("viewrap", 80)),
							 0); msg_f->me_flags &= ~MF_READONLY;
		fl_textedit_readonly(obj, 1);
		fl_set_object_callback(obj, cb_browser, num);
		fl_textedit_set_callback(obj, text_dbl_call,
								 FL_TEXTEDIT_DBL_CALLBACK);
		fl_set_object_shortcut(obj, "&1", 0);
		msg_f->me_text = obj;
	} else {
		obj =
		fl_add_textedit(FL_NORMAL_TEXTEDIT, 3, browserbottom, 799,
						browserheight + 30, "");
		fl_set_object_resize(obj, FL_RESIZE_ALL);
		fl_set_object_gravity(obj, NorthWestGravity, SouthEastGravity);
		fl_set_textedit_color(obj,
							  Config.getInt("EditBgCol", FL_MCOL),
							  Config.getInt("EditFgCol", FL_BLACK), FL_BLUE, 0);
		fl_set_textedit_wrap(obj,
							 Config.getInt("editwrap", -80), 0);
		if(Config.getInt("editpastecur", 1))
			fl_set_textedit_flags(obj, FL_TEXTEDIT_PASTE_CUR, -1);
		fl_set_object_callback(obj, cb_editor, num);
		msg_f->me_text = obj;
	}

	obj->u_ldata = num;

	obj =
	fl_add_button(FL_HIDDEN_BUTTON, 3,
				  browserbottom + browserheight + 30, 799, 2, "");
	fl_set_object_resize(obj, FL_RESIZE_X);
	fl_set_object_gravity(obj, SouthWestGravity, SouthEastGravity);
	fl_set_object_posthandler(obj, cb_mime_separator);
	obj->u_vdata = msg_f;

	if(msg_f->me_flags & MF_VIEW) {
		obj =
		fl_add_pixmapbutton(FL_NORMAL_BUTTON, 20, buttons_y_bottom, 35,
							33, "");
		fl_set_object_resize(obj, FL_RESIZE_NONE);
		fl_set_object_gravity(obj, NorthWestGravity, 0);
		obj->u_ldata = num;
		obj->u_vdata = const_cast < char *>("Exit viewer (X,Alt+X)");
		fl_set_pixmapbutton_data(obj, exit_xpm);
		fl_set_object_callback(obj, cb_mbutton_exit_view, num);
		fl_set_button_shortcut(obj, "Xx#X", 0);
		fl_set_object_posthandler(obj, post_handler);

		fl_set_form_atclose(form, close_view_form, obj);

		obj =
		fl_add_pixmapbutton(FL_NORMAL_BUTTON, 80, buttons_y_bottom, 35,
							33, "");
		fl_set_object_resize(obj, FL_RESIZE_NONE);
		fl_set_object_gravity(obj, NorthWestGravity, 0);
		fl_set_object_posthandler(obj, post_handler);
		obj->u_ldata = num;
		obj->u_vdata = const_cast < char *>("Previous unread message");
		fl_set_pixmapbutton_data(obj, prevu_xpm);
		fl_set_object_callback(obj, cb_mbutton_np, 1);

		obj =
		fl_add_pixmapbutton(FL_NORMAL_BUTTON, 117, buttons_y_bottom,
							35, 33, "");
		fl_set_object_resize(obj, FL_RESIZE_NONE);
		fl_set_object_gravity(obj, NorthWestGravity, 0);
		fl_set_object_posthandler(obj, post_handler);
		obj->u_ldata = num;
		obj->u_vdata = const_cast < char *>("Previous message (P,Alt+P)");
		fl_set_pixmapbutton_data(obj, prev_xpm);
		fl_set_object_callback(obj, cb_mbutton_np, 2);
		fl_set_button_shortcut(obj, "Pp#P", 0);

		obj =
		fl_add_pixmapbutton(FL_NORMAL_BUTTON, 154, buttons_y_bottom,
							35, 33, "");
		fl_set_object_resize(obj, FL_RESIZE_NONE);
		fl_set_object_gravity(obj, NorthWestGravity, 0);
		fl_set_object_posthandler(obj, post_handler);
		obj->u_ldata = num;
		obj->u_vdata = const_cast < char *>("Next message (N,Alt+N)");
		fl_set_pixmapbutton_data(obj, next_xpm);
		fl_set_object_callback(obj, cb_mbutton_np, 3);
		fl_set_button_shortcut(obj, "Nn#N", 0);

		obj =
		fl_add_pixmapbutton(FL_NORMAL_BUTTON, 191, buttons_y_bottom,
							35, 33, "");
		fl_set_object_resize(obj, FL_RESIZE_NONE);
		fl_set_object_gravity(obj, NorthWestGravity, 0);
		fl_set_object_posthandler(obj, post_handler);
		obj->u_ldata = num;
		obj->u_vdata = const_cast < char *>("Next unread message (Space)");
		fl_set_pixmapbutton_data(obj, nextu_xpm);
		fl_set_object_callback(obj, cb_mbutton_np, 4);
		fl_set_button_shortcut(obj, " ", 0);

		obj =
		fl_add_pixmapbutton(FL_NORMAL_BUTTON, 240, buttons_y_bottom,
							35, 33, "");
		fl_set_object_resize(obj, FL_RESIZE_NONE);
		fl_set_object_gravity(obj, NorthWestGravity, 0);
		fl_set_object_posthandler(obj, post_handler);
		obj->u_ldata = num;
		obj->u_vdata = const_cast < char *>("Reply to message (R,Alt+R)");
		fl_set_pixmapbutton_data(obj, reply_xpm);
		fl_set_object_callback(obj, cb_mbutton_reply, num);
		fl_set_button_shortcut(obj, "Rr#R", 0);

		obj =
		fl_add_pixmapbutton(FL_NORMAL_BUTTON, 277, buttons_y_bottom,
							35, 33, "");
		fl_set_object_resize(obj, FL_RESIZE_NONE);
		fl_set_object_gravity(obj, NorthWestGravity, 0);
		fl_set_object_posthandler(obj, post_handler);
		obj->u_ldata = num;
		obj->u_vdata = const_cast < char *>("Forward message (F,Alt+F)");
		fl_set_pixmapbutton_data(obj, forward_xpm);
		fl_set_object_callback(obj, cb_mbutton_forward, num);
		fl_set_button_shortcut(obj, "Ff#F", 0);

		obj =
		fl_add_pixmapbutton(FL_NORMAL_BUTTON, 330, buttons_y_bottom,
							35, 33, "");
		fl_set_object_resize(obj, FL_RESIZE_NONE);
		fl_set_object_gravity(obj, NorthWestGravity, 0);
		fl_set_object_posthandler(obj, post_handler);
		obj->u_ldata = num;
		obj->u_vdata =
		const_cast < char *>("Move to another folder (M,Alt+M)");
		fl_set_pixmapbutton_data(obj, move_xpm);
		fl_set_object_callback(obj, cb_mbutton_move, num);
		fl_set_button_shortcut(obj, "Mm#M", 0);

		obj =
		fl_add_pixmapbutton(FL_NORMAL_BUTTON, 367, buttons_y_bottom,
							35, 33, "");
		fl_set_object_resize(obj, FL_RESIZE_NONE);
		fl_set_object_gravity(obj, NorthWestGravity, 0);
		fl_set_object_posthandler(obj, post_handler);
		obj->u_ldata = num;
		obj->u_vdata = const_cast < char *>("Delete (D,Alt+D)");
		fl_set_pixmapbutton_data(obj, delete_xpm);
		fl_set_object_callback(obj, cb_mbutton_delete, num);
		fl_set_button_shortcut(obj, "Dd#D", 0);

		obj =
		fl_add_pixmapbutton(FL_NORMAL_BUTTON, 410, buttons_y_bottom,
							35, 33, "");
		fl_set_object_resize(obj, FL_RESIZE_NONE);
		fl_set_object_gravity(obj, NorthWestGravity, 0);
		fl_set_object_posthandler(obj, post_handler);
		obj->u_ldata = num;
		obj->u_vdata = const_cast < char *>("External viewer (V,Alt+V)");
		fl_set_pixmapbutton_data(obj, view_xpm);
		fl_set_object_callback(obj, cb_mbutton_view, num);
		fl_set_button_shortcut(obj, "Vv#V", 0);

		obj =
		fl_add_pixmapbutton(FL_NORMAL_BUTTON, 445, buttons_y_bottom,
							35, 33, "");
		fl_set_object_resize(obj, FL_RESIZE_NONE);
		fl_set_object_gravity(obj, NorthWestGravity, 0);
		fl_set_object_posthandler(obj, post_handler);
		obj->u_ldata = num;
		obj->u_vdata = const_cast < char *>("Print");
		fl_set_pixmapbutton_data(obj, print_xpm);
		fl_set_object_callback(obj, cb_mbutton_print, num);

		msg_f->me_abort = obj =
						  fl_add_pixmapbutton(FL_NORMAL_BUTTON, 480, buttons_y_bottom,
											  35, 33, "");
		fl_set_object_resize(obj, FL_RESIZE_NONE);
		fl_set_object_gravity(obj, NorthWestGravity, 0);
		fl_set_object_posthandler(obj, post_handler);
		obj->u_ldata = num;
		obj->u_vdata = const_cast < char *>("Abort");
		fl_set_pixmapbutton_data(obj, abort_xpm);
		fl_set_object_callback(obj, cb_button_abort, num);

		obj =
		fl_add_pixmapbutton(FL_NORMAL_BUTTON, 515, buttons_y_bottom,
							35, 33, "");
		fl_set_object_resize(obj, FL_RESIZE_NONE);
		fl_set_object_gravity(obj, NorthWestGravity, 0);
		fl_set_object_posthandler(obj, post_handler);
		obj->u_ldata = num;
		obj->u_vdata = const_cast < char *>("Help (H,Alt+H)");
		fl_set_pixmapbutton_data(obj, help_xpm);
		fl_set_object_callback(obj, cb_help_button, 10);
		fl_set_button_shortcut(obj, "Hh#H", 0);

	} else {
		obj =
		fl_add_pixmapbutton(FL_NORMAL_BUTTON, 57, buttons_y_bottom, 35,
							33, "");
		fl_set_object_resize(obj, FL_RESIZE_NONE);
		fl_set_object_gravity(obj, NorthWestGravity, 0);
		fl_set_object_posthandler(obj, post_handler);
		obj->u_ldata = num;
		obj->u_vdata = const_cast < char *>("Send (Alt+S)");
		fl_set_pixmapbutton_data(obj, send_xpm);
		fl_set_object_callback(obj, cb_mbutton_send, num);
		fl_set_button_shortcut(obj, "#S", 0);

		obj =
		fl_add_pixmapbutton(FL_NORMAL_BUTTON, 20, buttons_y_bottom, 35,
							33, "");
		fl_set_object_resize(obj, FL_RESIZE_NONE);
		fl_set_object_gravity(obj, NorthWestGravity, 0);
		fl_set_object_posthandler(obj, post_handler);
		obj->u_ldata = num;
		obj->u_vdata = const_cast < char *>("Exit editor (Alt+X)");
		fl_set_pixmapbutton_data(obj, exit_xpm);
		fl_set_object_callback(obj, cb_mbutton_exit_edit, num);
		fl_set_button_shortcut(obj, "#X", 0);

		fl_set_form_atclose(form, close_edit_form, obj);

		obj =
		fl_add_pixmapbutton(FL_NORMAL_BUTTON, 120, buttons_y_bottom,
							35, 33, "");
		fl_set_object_resize(obj, FL_RESIZE_NONE);
		fl_set_object_gravity(obj, NorthWestGravity, 0);
		fl_set_object_posthandler(obj, post_handler);
		obj->u_ldata = num;
		obj->u_vdata = const_cast < char *>("Insert file (Alt+I)");
		fl_set_pixmapbutton_data(obj, insert_xpm);
		fl_set_object_callback(obj, cb_mbutton_insert, num);
		fl_set_button_shortcut(obj, "#I", 0);

		obj =
		fl_add_pixmapbutton(FL_NORMAL_BUTTON, 160, buttons_y_bottom,
							35, 33, "");
		fl_set_object_resize(obj, FL_RESIZE_NONE);
		fl_set_object_gravity(obj, NorthWestGravity, 0);
		fl_set_object_posthandler(obj, post_handler);
		obj->u_ldata = num;
		obj->u_vdata = const_cast < char *>("Include original (Alt+Q)");
		fl_set_pixmapbutton_data(obj, insorig_xpm);
		fl_set_object_callback(obj, cb_mbutton_insorig, num);
		fl_set_button_shortcut(obj, "#Q", 0);

		obj =
		fl_add_pixmapbutton(FL_NORMAL_BUTTON, 200, buttons_y_bottom,
							35, 33, "");
		fl_set_object_resize(obj, FL_RESIZE_NONE);
		fl_set_object_gravity(obj, NorthWestGravity, 0);
		fl_set_object_posthandler(obj, post_handler);
		obj->u_ldata = num;
		obj->u_vdata = const_cast < char *>("Add signature (Alt+N)");
		fl_set_pixmapbutton_data(obj, sign_xpm);
		fl_set_object_callback(obj, cb_mbutton_sign, num);
		fl_set_button_shortcut(obj, "#N", 0);

		obj =
		fl_add_pixmapbutton(FL_NORMAL_BUTTON, 240, buttons_y_bottom,
							35, 33, "");
		fl_set_object_resize(obj, FL_RESIZE_NONE);
		fl_set_object_gravity(obj, NorthWestGravity, 0);
		fl_set_object_posthandler(obj, post_handler);
		obj->u_ldata = num;
		obj->u_vdata = const_cast < char *>("External editor");
		fl_set_pixmapbutton_data(obj, edit_xpm);
		fl_set_object_callback(obj, cb_mbutton_edit, num);

		obj =
		fl_add_pixmapbutton(FL_NORMAL_BUTTON, 280, buttons_y_bottom,
							35, 33, "");
		fl_set_object_resize(obj, FL_RESIZE_NONE);
		fl_set_object_gravity(obj, NorthWestGravity, 0);
		fl_set_object_posthandler(obj, post_handler);
		obj->u_ldata = num;
		obj->u_vdata = const_cast < char *>("Spell check (Alt+P)");
		fl_set_pixmapbutton_data(obj, spell_xpm);
		fl_set_object_callback(obj, cb_spell_button, num);
		fl_set_button_shortcut(obj, "#P", 0);

		obj =
		fl_add_pixmapbutton(FL_NORMAL_BUTTON, 320, buttons_y_bottom,
							35, 33, "");
		fl_set_object_resize(obj, FL_RESIZE_NONE);
		fl_set_object_gravity(obj, NorthWestGravity, 0);
		fl_set_object_posthandler(obj, post_handler);
		obj->u_ldata = num;
		obj->u_vdata = const_cast < char *>("Attach (Alt+T)");
		fl_set_pixmapbutton_data(obj, attach_xpm);
		fl_set_object_callback(obj, cb_attach_button, num);
		fl_set_button_shortcut(obj, "#T", 0);

		msg_f->me_abort = obj =
						  fl_add_pixmapbutton(FL_NORMAL_BUTTON, 360, buttons_y_bottom,
											  35, 33, "");
		fl_set_object_resize(obj, FL_RESIZE_NONE);
		fl_set_object_gravity(obj, NorthWestGravity, 0);
		fl_set_object_posthandler(obj, post_handler);
		obj->u_ldata = num;
		obj->u_vdata = const_cast < char *>("Abort");
		fl_set_pixmapbutton_data(obj, abort_xpm);
		fl_set_object_callback(obj, cb_button_abort, num);

		obj =
		fl_add_pixmapbutton(FL_NORMAL_BUTTON, 395, buttons_y_bottom,
							35, 33, "");
		fl_set_object_resize(obj, FL_RESIZE_NONE);
		fl_set_object_gravity(obj, NorthWestGravity, 0);
		fl_set_object_posthandler(obj, post_handler);
		obj->u_ldata = num;
		obj->u_vdata = const_cast < char *>("Help (Alt+H)");
		fl_set_pixmapbutton_data(obj, help_xpm);
		fl_set_object_callback(obj, cb_help_button, 11);
		fl_set_button_shortcut(obj, "#H", 0);

		if(autosave == NULL) {
			asave_timer = fl_add_timer(FL_HIDDEN_TIMER, 0, 0, 1, 2, "");
			fl_set_object_callback(asave_timer, cb_msg_autosave, 0);
			fl_set_timer(asave_timer,
						 Config.getInt("asavetime", 180));
			autosave = form;
		}
	}


	fl_end_form();
	fl_deactivate_object(msg_f->me_abort);
	fl_register_raw_callback(form, KeyPressMask, cb_pgupdown);
	fl_set_form_minsize(form, 600, 300);
	num_cascade = num % 12;
	if(Config.getInt("wplace", 1))
		fl_set_initial_placement(form, mfc_x + 20 * num_cascade,
								 mfc_y + 20 * num_cascade, mf_x, mf_y);
	else
		fl_set_form_size(form, mf_x, mf_y);

	if(msg_f->me_flags & MF_VIEW) {
		msg_f->me_to->wantkey = FL_KEY_SPECIAL;
		msg_f->me_from->wantkey = FL_KEY_SPECIAL;
		msg_f->me_subj->wantkey = FL_KEY_SPECIAL;
		fl_set_object_focus(form, msg_f->me_text);
		fl_show_form(form, FL_PLACE_FREE, FL_FULLBORDER, "MSGView");
	} else {
		fl_addto_choice(msg_f->me_to_type, "To");
		fl_addto_choice(msg_f->me_to_type, "Cc");
		fl_addto_choice(msg_f->me_to_type, "Bcc");
		fl_addto_choice(msg_f->me_to_type, "Nn");
		fl_addto_choice(msg_f->me_to_type, "Fcc");
		fl_set_choice(msg_f->me_to_type, 1);

		fl_addto_choice(msg_f->me_prior, "Very high");
		fl_addto_choice(msg_f->me_prior, "High");
		fl_addto_choice(msg_f->me_prior, "Normal");
		fl_addto_choice(msg_f->me_prior, "Low");
		fl_set_choice(msg_f->me_prior, 3);

		addr = addr1 = get_address(Config.get("from", "").c_str(), 0);
		while(addr1) {
			fl_addto_menu(fobj, get_full_addr_line(addr1));
			addr1 = addr1->next_addr;
		}
		discard_address(addr);

		for(k = 1; k <= MAX_EXTRA_HEADERS; k++) {
			sprintf(buf, "ExtraHeader%d", k);
			if(Config.exist(buf)) {
				strcpy(buf, Config.get(buf, "").c_str());
				if((hf = get_field(buf)) != NULL) {
					if(!strncasecmp(hf->f_name, "Subject", 7) &&
					   isdigit(hf->f_name[7]) && (hf->f_name[8] == '\0'))
						fl_addto_menu(sobj, hf->f_line);
					free(hf->f_line);
					free(hf);
				}
			}
		}

		if(msg_f->me_msg->header->Subject &&
		   *msg_f->me_msg->header->Subject)
			fl_set_object_focus(form, msg_f->me_text);
		else
			fl_set_object_focus(form, msg_f->me_subj);

		if(!(msg_f->me_msg->flags & SIGNED) &&
		   (Config.getInt("sattach", 2) == 3)) {
			fl_set_button(msg_f->me_sign, 1);
			msg_f->me_flags |= MF_SIGN;
		} else {
			fl_set_button(msg_f->me_sign, 0);
			msg_f->me_flags &= ~MF_SIGN;
		}

		if(Config.getInt("pgpsign", 0)) {
			fl_set_button(msg_f->me_pgp, 1);
			msg_f->me_flags |= MF_PGPSIGN;
		} else {
			fl_set_button(msg_f->me_pgp, 0);
			msg_f->me_flags &= ~MF_PGPSIGN;
		}

		fl_show_form(form, FL_PLACE_FREE, FL_FULLBORDER, "MSGEdit");
	}

	if((xwmh = XAllocWMHints()) != NULL) {
		xwmh->icon_pixmap = icon_MailEdit;
		xwmh->icon_mask = icon_MailEdit_sh;
		xwmh->flags = IconPixmapHint | IconMaskHint;
		XSetWMHints(fl_display, form->window, xwmh);
		XFree(xwmh);
	}

	if(Config.getInt("wplace", 1)) {
		mf_xofft = form->x - (mfc_x + 20 * num_cascade);
		mf_yofft = form->y - (mfc_y + 20 * num_cascade);
	}

	return msg_f;
}


int view_msg(struct _mail_msg *msg, int openwin) {
	struct msg_form *mf_ptr;
	int i, id;

	if(msg == NULL)
		return -1;

	if((msg->status & DELETED) || (msg->status & MNOTEXISTS))
		return -1;

	if(msg->status & LOCKED) {
		for(i = 0; i < MAX_MSG_FORMS; i++) {
			if((mf_arr[i] != NULL) && (mf_arr[i]->me_msg == msg))
				XMapRaised(fl_display, mf_arr[i]->me_form->window);
		}
		return -1;
	}

	if(msg->data == MSG_DAT_ENCAP) {
		for(i = 0; i < MAX_MSG_FORMS; i++) {
			if((mf_arr[i] != NULL) &&
			   (mf_arr[i]->me_flags & MF_VIEW) &&
			   (mf_arr[i]->me_msg == (struct _mail_msg *) msg->pdata))
				mf_arr[i]->me_flags |= MF_LOCKED;
		}
	}

	if(!openwin) {
		for(i = 0; i < MAX_MSG_FORMS; i++) {
			if((mf_arr[i] != NULL) &&
			   (mf_arr[i]->me_flags & MF_VIEW) &&
			   (mf_arr[i]->me_msg->data == MSG_DAT_EMPTY) &&
			   !(mf_arr[i]->me_flags & MF_LOCKED)) {
				mf_arr[i]->me_msg->status &= ~LOCKED;
				msg->free_text(mf_arr[i]->me_msg);
				mf_arr[i]->me_msg->update(mf_arr[i]->me_msg);
				redraw_msg(mf_arr[i]->me_msg);

				mf_arr[i]->me_msg = msg;
				update_msg(i);
				return 0;
			}
		}
	}

	for(i = 0; i < MAX_MSG_FORMS; i++) {
		if(mf_arr[i] == NULL)
			break;
	}

	if(i == MAX_MSG_FORMS) {
		display_msg(MSG_WARN, "view",
					"you can not have more then %d viewer/editor windows",
					MAX_MSG_FORMS);
		return -1;
	}
	id = i;

	if(msg->type & M_IMAP) {
		my_deactivate();
		set_cursor(main_form, XC_watch);

		if(!msg->get_file(msg)) {
			my_activate();
			set_cursor(main_form, 0);
			return -1;
		}

		my_activate();
		set_cursor(main_form, 0);
	}

	if((mf_ptr = (struct msg_form *) malloc(sizeof(struct msg_form))) ==
	   NULL) {
		display_msg(MSG_FATAL, "view", "malloc failed");
		exit(1);
	}

	mf_arr[id] = mf_ptr;

	mf_ptr->me_form = NULL;
	mf_ptr->me_from = mf_ptr->me_to = NULL;
	mf_ptr->me_to_list = mf_ptr->me_to_type = mf_ptr->me_subj = NULL;
	mf_ptr->me_text = mf_ptr->me_pixmap = mf_ptr->me_bitmap = NULL;
	mf_ptr->me_date = mf_ptr->me_mime = NULL;

	mf_ptr->me_lang = -1;
	mf_ptr->me_flags = MF_VIEW;
	mf_ptr->tofft = 0L;

	mf_ptr->me_msg = msg;
	switch_ttips();
	create_msg_form(mf_ptr, id);

	if(Config.getInt("sheader", 0))
		mf_ptr->me_flags |= MF_HEADER;

	update_msg(id);
	switch_ttips();

	return 0;
}

void set_edit_cursor(struct _mail_msg *msg, int cx, int cy) {
	int i;

	if(!msg || !(msg->status & LOCKED))
		return;

	for(i = 0; i < MAX_MSG_FORMS; i++) {
		if((mf_arr[i] != NULL) && (mf_arr[i]->me_msg == msg) &&
		   !(mf_arr[i]->me_flags & MF_VIEW)) {
			fl_set_textedit_cursorpos(mf_arr[i]->me_text, cx, cy, -1, 0);
			return;
		}
	}
}

int edit_msg(struct _mail_msg *msg) {
	struct msg_form *mf_ptr;
	int i, id;

	if(msg == NULL)
		return -1;

	if((msg->status & DELETED) || (msg->status & MNOTEXISTS))
		return -1;

	if(msg->status & LOCKED) {
		for(i = 0; i < MAX_MSG_FORMS; i++) {
			if((mf_arr[i] != NULL) && (mf_arr[i]->me_msg == msg))
				XMapRaised(fl_display, mf_arr[i]->me_form->window);
		}
		return 0;
	}

	for(i = 0; i < MAX_MSG_FORMS; i++)
		if(mf_arr[i] == NULL)
			break;

	if(i == MAX_MSG_FORMS) {
		display_msg(MSG_WARN, "view",
					"you can not have more then %d viewer/editor windows",
					MAX_MSG_FORMS);
		return -1;
	}

	id = i;

	if(msg->type & M_IMAP) {
		display_msg(MSG_WARN, "edit",
					"Editing changes will not be stored on the server");
		my_deactivate();
		set_cursor(main_form, XC_watch);
		if(!msg->get_file(msg)) {
			my_activate();
			set_cursor(main_form, 0);
			return -1;
		}

		my_activate();
		set_cursor(main_form, 0);
	}


	if((msg->flags & PGP_SIGNED) || (msg->flags & PGP_ENCRYPTED))
		display_msg(MSG_WARN, "edit",
					"Editing of PGP signed/encrypted message is not recommended");
	if((mf_ptr = (struct msg_form *) malloc(sizeof(struct msg_form))) ==
	   NULL) {
		display_msg(MSG_FATAL, "edit", "malloc failed");
		exit(1);
	}

	mf_arr[id] = mf_ptr;

	mf_ptr->me_form = NULL;
	mf_ptr->me_from = mf_ptr->me_to = NULL;
	mf_ptr->me_to_list = mf_ptr->me_to_type = mf_ptr->me_subj = NULL;
	mf_ptr->me_text = mf_ptr->me_pixmap = mf_ptr->me_bitmap = NULL;
	mf_ptr->me_date = mf_ptr->me_mime = NULL;

	mf_ptr->me_lang = -1;
	mf_ptr->me_flags = 0;
	mf_ptr->tofft = 0L;

	mf_ptr->me_msg = msg;
	switch_ttips();
	create_msg_form(mf_ptr, id);

	update_msg(id);
	switch_ttips();

	return 0;
}

struct _mail_addr *get_msgaddr_byline(int id, int line, int *type) {
	struct msg_form *mf_ptr;
	struct _mail_msg *msg;
	struct _mail_addr *to_p;
	struct _news_addr *naddr;
	int i;
	char *fcc;

	mf_ptr = mf_arr[id];
	if(!mf_ptr)
		return NULL;

	msg = mf_ptr->me_msg;
	if(!msg)
		return NULL;

	i = 0;
	for(to_p = msg->header->To; to_p; to_p = to_p->next_addr) {
		i++;
		if(i == line) {
			*type = TO_TYPE;
			return to_p;
		}
	}

	for(to_p = msg->header->Cc; to_p; to_p = to_p->next_addr) {
		i++;
		if(i == line) {
			*type = CC_TYPE;
			return to_p;
		}
	}

	for(to_p = msg->header->Bcc; to_p; to_p = to_p->next_addr) {
		i++;
		if(i == line) {
			*type = BCC_TYPE;
			return to_p;
		}
	}

	for(naddr = msg->header->News; naddr; naddr = naddr->next) {
		i++;
		if(i == line) {
			*type = NN_TYPE;
			return(struct _mail_addr *) naddr;
		}
	}

	fcc = NULL;
	while((fcc = scan_fcc_list(msg, fcc)) != NULL) {
		i++;
		if(i == line) {
			*type = FCC_TYPE;
			return(struct _mail_addr *) fcc;
		}
	}

	return NULL;
}

void display_addresses(int id) {
	static int ftype;
	char addrbuf[127], *fcc;
	struct msg_form *mf_ptr;
	struct _mail_msg *msg;
	struct _mail_addr *to_p;
	struct _news_addr *naddr;

	mf_ptr = mf_arr[id];
	if(!mf_ptr)
		return;

	msg = mf_ptr->me_msg;
	if(!msg)
		return;

	fl_clear_browser(mf_ptr->me_to_list);

	ftype = -1;
	for(to_p = msg->header->To; to_p; to_p = to_p->next_addr)
		fl_add_browser_line(mf_ptr->me_to_list,
							get_charset_addr_line("To: ", to_p,
												  ftype <
												  0 ? &ftype : NULL));

	for(to_p = msg->header->Cc; to_p; to_p = to_p->next_addr)
		fl_add_browser_line(mf_ptr->me_to_list,
							get_charset_addr_line("Cc: ", to_p,
												  ftype <
												  0 ? &ftype : NULL));

	for(to_p = msg->header->Bcc; to_p; to_p = to_p->next_addr)
		fl_add_browser_line(mf_ptr->me_to_list,
							get_charset_addr_line("Bcc:", to_p,
												  ftype <
												  0 ? &ftype : NULL));

	for(naddr = msg->header->News; naddr; naddr = naddr->next) {
		snprintf(addrbuf, sizeof(addrbuf), "Nn: %s", naddr->name);
		fl_add_browser_line(mf_ptr->me_to_list, addrbuf);
	}

	fcc = NULL;
	while((fcc = scan_fcc_list(msg, fcc)) != NULL) {
		snprintf(addrbuf, sizeof(addrbuf), "Fcc: %s", fcc);
		fl_add_browser_line(mf_ptr->me_to_list, addrbuf);
	}

	fl_select_browser_line(mf_ptr->me_to_list, 1);

	if(ftype >= 0) {
		fl_set_browser_fontstyle(mf_ptr->me_to_list,
			charset_style_from_code(supp_charsets[ftype].charset_code));
		fl_set_browser_fontsize(mf_ptr->me_to_list,
			charset_size_from_code(supp_charsets[ftype].charset_code));
	} else {
		fl_set_browser_fontstyle(mf_ptr->me_to_list,
			charset_style_from_code(supp_charsets[def_charset].charset_code));
		fl_set_browser_fontsize(mf_ptr->me_to_list,
			charset_size_from_code(supp_charsets[def_charset].charset_code));
	}

	return;
}

int update_msg(int id) {
	static int ftype;
	int hfsize, hfstyle;
	struct msg_form *mf_ptr;
	struct _mail_msg *msg;
	struct _head_field *hf;
	char str[255];
	char subbuf[MAX_FIELD_LEN];
	char *face;

	mf_ptr = mf_arr[id];
	if(!mf_ptr)
		return -1;

	msg = mf_ptr->me_msg;
	if(!msg)
		return -1;

	if(mf_ptr->me_flags & MF_VIEW) {
		hfsize = Config.getInt("ViewFSize", FL_DEFAULT_SIZE);
		hfstyle = Config.getInt("ViewFStyle", FL_NORMAL_STYLE);
	} else {
		hfsize = Config.getInt("EditFSize", FL_DEFAULT_SIZE);
		hfstyle = Config.getInt("EditFStyle", FL_NORMAL_STYLE);
	}

	if((msg->type & M_IMAP) && (msg->flags & H_ONLY)) {
		msg_deactivate(id);
		set_cursor(mf_ptr->me_form, XC_watch);

		if(!msg->get_file(msg)) {
			msg_activate(id);
			set_cursor(mf_ptr->me_form, 0);
			return -1;
		}

		msg_activate(id);
		set_cursor(mf_ptr->me_form, 0);
	}

	msg->get_header(msg);

	fl_freeze_form(mf_ptr->me_form);
	fl_set_input_return(mf_ptr->me_subj, FL_RETURN_END_CHANGED);
	fl_set_input_return(mf_ptr->me_from, FL_RETURN_END_CHANGED);

	ftype = 0;
	face = NULL;
	if((mf_ptr->me_flags & MF_VIEW)
	   && Config.getInt("usefaces", 0)) {
#ifdef  WITH_FACES
		if((face = get_msg_face(msg)) != NULL) {
			fl_hide_object(mf_ptr->me_pixmap);
			fl_show_object(mf_ptr->me_bitmap);
			fl_set_bitmap_data(mf_ptr->me_bitmap, 48, 48,
							   (unsigned char *) face);
		} else
#endif
			if((face = find_face(msg->header->From, &ftype)) != NULL) {
			switch(ftype) {
				case FACE_XPM:
					fl_hide_object(mf_ptr->me_bitmap);
					fl_free_pixmap_pixmap(mf_ptr->me_pixmap);
					fl_set_pixmap_file(mf_ptr->me_pixmap, face);
					fl_show_object(mf_ptr->me_pixmap);
					break;

				case FACE_XBM:
					fl_hide_object(mf_ptr->me_pixmap);
					fl_set_bitmap_file(mf_ptr->me_bitmap, face);
					fl_show_object(mf_ptr->me_bitmap);
					break;

				default:
					break;
			}
		}
	}

	if(!face) {
		fl_hide_object(mf_ptr->me_bitmap);
		if(mf_ptr->me_flags & MF_VIEW)
			fl_free_pixmap_pixmap(mf_ptr->me_pixmap);
		if(msg->flags & UNREAD)
			fl_set_pixmap_data(mf_ptr->me_pixmap, icon_mail_xpm);
		else
			fl_set_pixmap_data(mf_ptr->me_pixmap, icon_nomail_xpm);
		fl_show_object(mf_ptr->me_pixmap);
	}

	ftype = -1;
	fl_set_input(mf_ptr->me_from,
				 get_charset_addr_line(NULL, msg->header->From, &ftype));
	if(ftype >= 0)
		fl_set_object_lstyle(mf_ptr->me_from,
			charset_style_from_code(supp_charsets[ftype].charset_code));
	else
		fl_set_object_lstyle(mf_ptr->me_from, hfstyle);
	fl_set_object_lsize(mf_ptr->me_from, hfsize);

	if(mf_ptr->me_flags & MF_VIEW) {
		strftime(str, 40, "%c", localtime(&msg->header->snt_time));
		fl_set_object_label(mf_ptr->me_date,
							((hf = find_field(msg, "Date"))
							 || (hf =
								 find_field(msg,
											"X-RDate"))) ? hf->
							f_line : str);

		if(msg->header->Sender) {
			ftype = -1;
			fl_set_input(mf_ptr->me_sender,
						 get_charset_addr_line(NULL, msg->header->Sender,
											   &ftype));
			if(ftype >= 0)
				fl_set_object_lstyle(mf_ptr->me_sender,
					charset_style_from_code(supp_charsets[ftype].charset_code));
			else
				fl_set_object_lstyle(mf_ptr->me_sender, hfstyle);
			fl_set_object_lsize(mf_ptr->me_sender, hfsize);
		} else
			fl_set_input(mf_ptr->me_sender, "");
	} else {
		switch(get_msg_priority(mf_ptr->me_msg)) {
			case 1:
				fl_set_choice(mf_ptr->me_prior, 1);
				break;

			case 2:
				fl_set_choice(mf_ptr->me_prior, 2);
				break;

			case 3:
				fl_set_choice(mf_ptr->me_prior, 3);
				break;

			case 4:
			case 5:
				fl_set_choice(mf_ptr->me_prior, 4);
				break;
		}
	}

	display_addresses(id);

	ftype = -1;
	if(msg->header->Subject) {
		snprintf(subbuf, sizeof(subbuf), "%s", rfc1522_decode(msg->header->Subject, &ftype));
		fl_set_input(mf_ptr->me_subj, subbuf);
		if(ftype >= 0)
			fl_set_object_lstyle(mf_ptr->me_subj,
				charset_style_from_code(supp_charsets[ftype].charset_code));
		else
			fl_set_object_lstyle(mf_ptr->me_subj, hfstyle);
	} else {
		fl_set_input(mf_ptr->me_subj, "");

		if(mf_ptr->me_flags & MF_VIEW)
			strcpy(subbuf, "*No Subject*");
		else
			strcpy(subbuf, "*New Mail*");
		fl_set_object_lstyle(mf_ptr->me_subj, hfstyle);
	}
	fl_set_object_lsize(mf_ptr->me_subj, hfsize);

	fl_set_form_title(mf_ptr->me_form, subbuf);
	XSetIconName(fl_display, mf_ptr->me_form->window, subbuf);

	if((msg->flags & UNREAD) && (hf = need_read_confirm(msg))) {
		fl_clear_textedit(mf_ptr->me_text);

		fl_clear_browser(mf_ptr->me_mime);

		fl_unfreeze_form(mf_ptr->me_form);
		switch(Config.getInt("vconfirm", 1)) {
			case 3:
				break;

			case 2:
				if(display_msg
				   (MSG_QUEST, "Confirm reading", "Send confirmation to %s?",
					hf->f_line)) {
					fl_deactivate_all_forms();
					set_cursor(mf_ptr->me_form, XC_watch);
					read_confirm(msg);
					set_cursor(mf_ptr->me_form, 0);
					fl_activate_all_forms();
				} else
					delete_read_confirm(msg);
				break;

			case 1:
			default:
				fl_deactivate_all_forms();
				set_cursor(mf_ptr->me_form, XC_watch);
				read_confirm(msg);
				set_cursor(mf_ptr->me_form, 0);
				fl_activate_all_forms();
				break;
		}
		fl_freeze_form(mf_ptr->me_form);
	}

	if(msg->flags & UNREAD) {
		msg->flags &= ~UNREAD;
		if(msg->folder && msg->folder->unread_num)
			msg->folder->unread_num--;
		msg->update(msg);
	}
	update_title();
	display_msg_text(mf_ptr);

	msg->status |= LOCKED;
	if(!(mf_ptr->me_flags & MF_VIEW)) {
		if(msg->flags & PGP_SIGNED) {
			mf_ptr->me_flags |= MF_READONLY;
			fl_textedit_readonly(mf_ptr->me_text, 1);
		} else {
			mf_ptr->me_flags &= ~MF_READONLY;
			fl_textedit_readonly(mf_ptr->me_text, 0);
		}
		fl_set_button(mf_ptr->me_pgp, mf_ptr->me_flags & MF_PGPSIGN);
	}

	mf_ptr->me_text->redraw = 1;
	fl_set_input_return(mf_ptr->me_subj, FL_RETURN_ALWAYS);
	fl_set_input_return(mf_ptr->me_from, FL_RETURN_ALWAYS);
	if(mf_ptr->me_flags & MF_VIEW)
		fl_set_object_focus(mf_ptr->me_form, mf_ptr->me_text);
	fl_unfreeze_form(mf_ptr->me_form);
	redraw_msg(msg);
	redraw_fld_line(msg->folder);

	return 0;
}

void release_orig(int id) {
	int i, released;
	struct _mail_msg *pmsg;

	if(!mf_arr[id] || !mf_arr[id]->me_msg)
		return;

	pmsg = (struct _mail_msg *) mf_arr[id]->me_msg->pdata;
	released = 0;

	if(mf_arr[id]->me_msg->data == MSG_DAT_ORIG) {
		for(i = 0; i < MAX_MSG_FORMS; i++) {
			if(mf_arr[i] && (mf_arr[i]->me_msg == pmsg)) {
				mf_arr[i]->me_flags &= ~MF_LOCKED;
				released = 1;
				break;
			}
		}
	} else if(mf_arr[id]->me_msg->data == MSG_DAT_ENCAP) {
		for(i = 0; i < MAX_MSG_FORMS; i++) {
			if(mf_arr[i] && (mf_arr[i]->me_msg == pmsg)) {
				mf_arr[i]->me_flags &= ~MF_LOCKED;
				released = 1;
				break;
			}
		}
	} else
		return;

	if(!released) {
		((struct _mail_msg *) mf_arr[id]->me_msg->pdata)->status &= ~LOCKED;
		redraw_msg((struct _mail_msg *) mf_arr[id]->me_msg->pdata);
	}

	mf_arr[id]->me_msg->data = MSG_DAT_EMPTY;
	mf_arr[id]->me_msg->pdata = NULL;

	return;
}

void end_msg(int id) {
	struct _mail_folder *fld;
	int i;

	if(mf_arr[id] == NULL)
		return;

	if(mf_arr[id]->me_flags & MF_LOCKED)
		return;

	switch_ttips();
	tobj = NULL;
	if(mf_arr[id]->me_msg) {
		fld = mf_arr[id]->me_msg->folder;
		release_orig(id);
		mf_arr[id]->me_msg->status &= ~LOCKED;
		mf_arr[id]->me_msg->update(mf_arr[id]->me_msg);
		redraw_msg(mf_arr[id]->me_msg);

		if(mf_arr[id]->me_msg->flags & M_TEMP) {
			mf_arr[id]->me_msg->flags &= ~M_TEMP;
			mf_arr[id]->me_msg->status |= DELPERM;
			mf_arr[id]->me_msg->mdelete(mf_arr[id]->me_msg);
			mf_arr[id]->me_msg = NULL;
		} else
			if((mf_arr[id]->me_msg->status & DELETED) &&
			   mf_arr[id]->me_msg->folder) {
			mf_arr[id]->me_msg->status &= ~DELETED;
			mf_arr[id]->me_msg->status |= DELPERM;
			mf_arr[id]->me_msg->mdelete(mf_arr[id]->me_msg);
			mf_arr[id]->me_msg = NULL;
			redraw_fld(trash);
			redraw_fld(fld);
		} else
			if((mf_arr[id]->me_msg->status & MOVED) &&
			   mf_arr[id]->me_msg->folder) {
			mf_arr[id]->me_msg->status &= ~MOVED;
			draft->move(mf_arr[id]->me_msg, draft);
			mf_arr[id]->me_msg = NULL;
			redraw_fld(draft);
			redraw_fld(fld);
		}
	}

	destruct_msg(mf_arr[id]);
	mf_arr[id] = NULL;
	switch_ttips();
	if(!main_form) {
		for(i = 0; i < MAX_MSG_FORMS; i++) {
			if(mf_arr[i] != NULL)
				return;
		}
		clean_exit(0);
	}
}

void destruct_msg(struct msg_form *mf) {
	mf_x = mf->me_form->w;
	mf_y = mf->me_form->h;
	if(mf == mf_arr[0]) {
		mfc_x = mf->me_form->x - mf_xofft;
		mfc_y = mf->me_form->y - mf_yofft;
		if(mfc_x < 0)
			mfc_x = mf->me_form->x;
		if(mfc_y < 0)
			mfc_y = mf->me_form->y;
	}

	if(autosave == mf->me_form) {
		autosave = NULL;
		asave_timer = NULL;
	}

	if (mf->me_lang != -1)
	    fl_freepup(mf->me_lang);

	fl_hide_form(mf->me_form);
	fl_free_form(mf->me_form);
	free(mf);
}

char *form_to_msg(int num, int update) {
	struct msg_form *mf_ptr;
	struct _mail_msg *msg;
	char *adr;

	mf_ptr = mf_arr[num];
	if(mf_ptr == NULL)
		return NULL;

	msg = mf_ptr->me_msg;
	if(msg == NULL)
		return NULL;

	adr = (char *) fl_get_input(mf_ptr->me_subj);
	if(msg->header->Subject)
		free(msg->header->Subject);
	msg->header->Subject = strlen(adr) ? strdup(adr) : NULL;

	discard_address(msg->header->From);
	msg->header->From =
	get_address((char *) fl_get_input(mf_ptr->me_from),
				ADDR_IGNORE_COMMAS);
	discard_address(msg->header->From->next_addr);
	msg->header->From->next_addr = NULL;

	cb_addr_addto(mf_ptr->me_to, num);

	return compose_msg_text(mf_ptr, update);
}

void ext_view_exit(struct _proc_info *pinfo) {
	struct msg_form *mf;

	if(!pinfo)
		return;

	unlink((char *) pinfo->u_data);
	free(pinfo->u_data);
	mf = mf_arr[pinfo->ul_data];
	if(mf) {
		mf->me_flags &= ~MF_LOCKED;
		fl_activate_form(mf->me_form);
	}
}

void ext_view_msg(int num, int asis) {
	struct msg_form *mf;
	struct _mail_msg *msg;
	struct _mime_msg *mime;
	struct _proc_info pinfo;
	char mfile[64];
	char buf[255];
	FILE *m_tmp, *mmfd;
	char *p;
	int i;

	mf = mf_arr[num];

	if(!mf || !(mf->me_flags & MF_VIEW) || (mf->me_flags & MF_LOCKED))
		return;

	if((msg = mf->me_msg) == NULL)
		return;

	strcpy(mfile, get_temp_file("extview"));
	if((m_tmp = fopen(mfile, "w")) == NULL) {
		display_msg(MSG_WARN, "ext view", "Can not open file %s", mfile);
		return;
	}

	if(!(mmfd = fopen(msg->get_file(mf->me_msg), "r"))) {
		display_msg(MSG_WARN, "Can not open message file", "%s",
					mf->me_msg->get_file(mf->me_msg));
		fclose(m_tmp);
		return;
	}

	if(mf->me_flags & MF_HEADER) {
		while(fgets(buf, 255, mmfd) && (strlen(buf) > 1))
			fputs(buf, m_tmp);

		fputs("\n", m_tmp);
	} else
		fseek(mmfd, msg->header->header_len, SEEK_SET);

	if(asis) {
		while(fgets(buf, 255, mmfd))
			fputs(buf, m_tmp);
	} else {
		mime = get_text_part(msg);

		if(mime == NULL) {
			mime = msg->mime;
			while(mime) {
				if((mime->flags & PREAMBLE) || (mime->flags & EPILOG))
					break;
				mime = mime->mime_next;
			}
		}

		if(mime == NULL) {
			fclose(m_tmp);
			fclose(mmfd);
			display_msg(MSG_WARN, "external viewer", "Empty message");
			return;
		}

		fseek(mmfd, mime->m_start, SEEK_SET);
		if(mime->boundary && (mime->flags & (TEXT_PART | ATTACHMENT))) {
			while(fgets(buf, 255, mmfd)) {
				if(strlen(buf) <= 1)
					break;
			}
		}

		(*mime->encoding->ce_dec) (NULL, &i);
		while((ftell(mmfd) < mime->m_end) && fgets(buf, 255, mmfd)) {
			if((p = (*mime->encoding->ce_dec) (buf, &i)) == NULL)
				continue;
			fputs(p, m_tmp);
		}
		p = (*mime->encoding->ce_dec) (NULL, &i);
		if(p && (strlen(p) > 1))
			fputs(p, m_tmp);
	}

	fclose(m_tmp);
	fclose(mmfd);

	init_pinfo(&pinfo);
	pinfo.wait = WAIT_ASYNC;
	pinfo.u_data = strdup(mfile);
	pinfo.ul_data = num;
	pinfo.handle = ext_view_exit;

	fl_deactivate_form(mf->me_form);
	mf->me_flags |= MF_LOCKED;
	if(file_view(mfile, &pinfo) == -1)
		ext_view_exit(&pinfo);

	return;
}

void ext_edit_exit(struct _proc_info *pinfo) {
	struct msg_form *mf;

	if(!pinfo)
		return;

	free(pinfo->u_data);
	mf = mf_arr[pinfo->ul_data];
	if(!mf)
		return;

	update_mime(mf->me_msg);

	mf->me_flags &= ~MF_LOCKED;
	fl_activate_object(mf->me_text);
	fl_freeze_form(mf->me_form);
	display_msg_text(mf);
	fl_unfreeze_form(mf->me_form);

	return;
}

void ext_edit_msg(int num) {
	struct msg_form *mf;
	struct _proc_info pinfo;
	char command[255];
	char *mfile;
	char *e;
	size_t i;
	int added = 0;

	mf = mf_arr[num];

	if(!mf || (mf->me_flags & MF_VIEW))
		return;

	if((mfile = compose_msg_text(mf, 0)) == NULL)
		return;

	mf->me_flags |= MF_CHANGED;
	mf->me_flags |= MF_LOCKED;
	fl_deactivate_object(mf->me_text);

	e = const_cast<char *>(Config.get("extedit", "/usr/bin/X11/xedit").c_str());
	command[0] = '\0';
	for(i = 0; i < strlen(e); i++) {
		if((e[i] == '$') && (e[i + 1] == 'f') && i && (e[i - 1] == ' ')) {
			added = 1;
			i++;
			strcat(command, mfile);
		} else {
			command[strlen(command) + 1] = '\0';
			command[strlen(command)] = e[i];
		}
	}

	if(!added) {
		strcat(command, " ");
		strcat(command, mfile);
		added = 1;
	}

	init_pinfo(&pinfo);
	pinfo.wait = WAIT_ASYNC;
	pinfo.u_data = strdup(mfile);
	pinfo.ul_data = num;
	pinfo.handle = ext_edit_exit;

	if(exec_child(command, &pinfo) == -1)
		ext_edit_exit(&pinfo);

	return;
}

void ext_fulledit_exit(struct _proc_info *pinfo) {
	struct msg_form *mf;
	struct _mail_msg *msg, *msg1;
	int ohflags;

	if(!pinfo)
		return;

	mf = mf_arr[pinfo->ul_data];
	if(!mf) {
		free(pinfo->u_data);
		return;
	}
	msg = mf->me_msg;
	ohflags = msg->header->flags;

	if((msg1 = get_message(msg->num, get_file_folder(msg))) == NULL) {
		display_msg(MSG_WARN, "edit", "The message is invalid");
		free(pinfo->u_data);
		return;
	}
	msg1->get_header(msg1);

	msg_cache_del(msg);
	if(msg->msg_body)
		msg->free_text(msg);
	discard_message_header(msg);
	if(msg->mime)
		discard_mime(msg->mime);
	msg->mime = NULL;
	discard_message_header(msg);

	msg->header = msg1->header;
	msg->header->flags = ohflags;
	msg->msg_len = msg1->msg_len;

	msg1->header = NULL;
	discard_message(msg1);

	mf->me_flags &= ~MF_LOCKED;
	update_msg(pinfo->ul_data);
	free(pinfo->u_data);

	return;
}

void ext_fulledit_msg(int num) {
	struct msg_form *mf;
	struct _mail_msg *msg;
	struct _proc_info pinfo;
	char command[255];
	char *mfile;
	char *e;
	size_t i;
	int added = 0;

	mf = mf_arr[num];
	if(!mf || (mf->me_flags & MF_VIEW))
		return;

	msg = mf->me_msg;
	form_to_msg(num, 1);
	if((mfile = msg->get_file(msg)) == NULL)
		return;

	mf->me_flags |= MF_CHANGED;
	mf->me_flags |= MF_LOCKED;
	msg->status |= MMODIFIED;

	e = const_cast<char *>(Config.get("extedit", "/usr/bin/X11/xedit").c_str());
	command[0] = '\0';
	for(i = 0; i < strlen(e); i++) {
		if((e[i] == '$') && (e[i + 1] == 'f')) {
			added = 1;
			strcat(command, mfile);
		} else {
			command[strlen(command) + 1] = '\0';
			command[strlen(command)] = e[i];
		}
	}

	if(!added) {
		strcat(command, " ");
		strcat(command, mfile);
		added = 1;
	}

	init_pinfo(&pinfo);
	pinfo.wait = WAIT_ASYNC;
	pinfo.u_data = strdup(mfile);
	pinfo.ul_data = num;
	pinfo.handle = ext_fulledit_exit;

	if(exec_child(command, &pinfo) == -1)
		ext_edit_exit(&pinfo);

	return;
}

void display_msg_text(struct msg_form *mf) {
	char buf[1024+1];
	char * buf2 = NULL;
	int buf2_len = 0;
	char prefix[17];
	u_long len;
	int wascr, i, nl, markincl, showurl, col, linenum, headerlines = 0;
	struct _mime_msg *mime;
	struct _pop_src *popsrc;
	char *p, *p1;
	struct _mail_msg *msg;
	char *mname;
	FILE *mfd = NULL;
	char *text = NULL;
	struct _url_spec *url, *urls;
	int expgrowth = 1;
	int index = 0;
	int ch_got = 0;

	if(!mf || !mf->me_msg)
		return;

	msg = mf->me_msg;

	fl_clear_browser(mf->me_mime);
	fl_clear_textedit(mf->me_text);

	if(msg->flags & H_ONLY) {
		fl_unfreeze_form(mf->me_form);
		if(msg->type & M_IMAP) {
			mf_deactivate(mf);
			set_cursor(mf->me_form, XC_watch);
			msg->status |= LOCKED;
			p = msg->get_file(msg);
			msg->status &= ~LOCKED;
			set_cursor(mf->me_form, 0);
			mf_activate(mf);
			fl_freeze_form(mf->me_form);
			if(p == NULL)
				return;
		} else {
			if(((popsrc = get_msg_popsrc(msg)) != NULL) &&
			   display_msg(MSG_QUEST,
						   "Message body resides on the POP server",
						   "Do you want to retrieve it?")) {
				mf_deactivate(mf);
				set_cursor(mf->me_form, XC_watch);
				pop_getfull_msg(popsrc, msg);
				set_cursor(mf->me_form, 0);
				mf_activate(mf);
				fl_freeze_form(mf->me_form);
			} else {
				fl_freeze_form(mf->me_form);
				return;
			}
		}
	} else if (msg->type == M_MBOX)
	    /* need to retrieve message */
	    msg->get_file(msg);


	if(msg->mime == NULL)
		mime_scan(msg);

	mime = msg->mime;

	i = 0;
	while(mime) {
		if(!(mime->flags & ATTACHMENT) || (mime->flags & TEXT_PART)) {
			mime = mime->mime_next;
			continue;
		}
		i++;
		fl_add_browser_line(mf->me_mime, get_mime_line(i, msg, mime));
		mime = mime->mime_next;
	}

	fl_select_browser_line(mf->me_mime, 1);

	len = 0;
	nl = 0;

	if(mf->me_flags & MF_VIEW) {
		strncpy(prefix, Config.get("prefix", ">").c_str(), 16);
		markincl = Config.getInt("markincl", 0);
		showurl = Config.getInt("showurl", 0);
		mime = get_view_part(msg);

		if(mime && mime->charset &&
		   (mime->charset->charset_code != CHAR_UNKNOWN)) {
			set_menu_chset(mf->me_lang, mime->charset);

			fl_set_textedit_fontstyle(mf->me_text,
				charset_style_from_code(mime->charset->charset_code));
			fl_set_textedit_fontsize(mf->me_text,
				charset_size_from_code(mime->charset->charset_code));

			fl_set_browser_fontsize(mf->me_mime,
				charset_size_from_code(mime->charset->charset_code));

			fl_set_browser_fontstyle(mf->me_mime,
				charset_style_from_code(mime->charset->charset_code));
		} else {
			set_menu_chset(mf->me_lang, &supp_charsets[DEFAULT_CHARSET]);

			fl_set_browser_fontsize(mf->me_mime,
				charset_size_from_code(supp_charsets[DEFAULT_CHARSET].charset_code));
			fl_set_textedit_fontsize(mf->me_text,
				charset_size_from_code(supp_charsets[DEFAULT_CHARSET].charset_code));

			fl_set_browser_fontstyle(mf->me_mime,
				charset_style_from_code(supp_charsets[DEFAULT_CHARSET].charset_code));
			fl_set_textedit_fontstyle(mf->me_text,
				charset_style_from_code(supp_charsets[DEFAULT_CHARSET].charset_code));
		}

		if(mf->me_flags & MF_HEADER) {
#ifndef MMAP_MSG
			if((mfd = fopen(msg->get_file(mf->me_msg), "r")) == NULL) {
				display_msg(MSG_WARN, "Can not open message file", "%s",
							msg->get_file(mf->me_msg));
				return;
			}
#else
			if(msg->get_text(msg, NULL) != 0) {
				display_msg(MSG_WARN, "view", "Can not access message");
				return;
			}
#endif

			col = Config.getInt("headcolor", FL_BLUE);

			while((msg_tell(mfd) < msg->header->header_len)
				  && msg_gets(buf, 1024, mfd) && (strlen(buf) > 1)) {
				strip_newline(buf);
				p = (mime && mime->charset
					 && mime->charset->decode) ? (*mime->charset->
												  decode) (buf) : buf;
				if(p == NULL)
					continue;
				fl_add_textedit_line(mf->me_text, p);
				fl_set_textedit_line_color(mf->me_text,
					fl_get_textedit_maxline(mf->me_text) - 1, -1, col);
#ifdef HAVE_REGCOMP
				url = highlight_urls(buf);
				if (url != NULL) {
					int linenum;

					linenum = fl_get_textedit_maxline(mf->me_text) - 1;
					fl_set_textedit_blockattr(mf->me_text, linenum, linenum,
						url->url_s, url->url_e, showurl | ATTR_UNDERLINE);
					free(url);
				}
#endif
			}

			fl_add_textedit_line(mf->me_text, "");
			headerlines = fl_get_textedit_maxline(mf->me_text);
			if(Config.getInt("sheader", 0))
				fl_set_textedit_vscrollbar(mf->me_text, 1);
		}

		if(mime == NULL) {
			display_msg(MSG_STAT, NULL, "View: Nothing to display");
#ifndef MMAP_MSG
			fclose(mfd);
#endif
			msg->free_text(msg);
			return;
		}
#ifndef MMAP_MSG
		if((mfd == NULL) &&
		   (mfd = fopen(msg->get_file(mf->me_msg), "r")) == NULL) {
			display_msg(MSG_WARN, "Can not open message file", "%s",
						msg->get_file(mf->me_msg));
			return;
		}
#else
		msg->free_text(msg);
		if(msg->get_text(msg, mime) != 0) {
			display_msg(MSG_WARN, "view", "Can not access message");
			return;
		}
#endif
		if((mime = get_view_part(msg)) == NULL)
			return;

		msg_seek(mfd, mime->m_start, SEEK_SET);

		if(mime->boundary && (mime->flags & (TEXT_PART | ATTACHMENT))) {
			while(msg_gets(buf, 1024, mfd)) {
				strip_newline(buf);
				if(strlen(buf) < 1)
					break;

			}
		} else if(mime->boundary && (mime->flags & EPILOG))
			msg_gets(buf, 1024, mfd);

#ifndef MMAP_MSG
		if(ferror(mfd) || feof(mfd)) {
			display_msg(MSG_WARN, "VIEW", "Error reading message");
			fclose(mfd);
			return;
		}
#endif

		wascr = 1;
		(*mime->encoding->ce_dec) (NULL, &i);
		while((msg_tell(mfd) < mime->m_end) && msg_gets(buf, 1024, mfd)) {

			if((p = (*mime->encoding->ce_dec) (buf, &i)) == NULL)
				continue;

			p1 = mime->charset->decode ? (*mime->charset->decode) (p) : p;

			while(1) {
				if((p = strchr(p1, '\n')) != NULL) {
					*p = '\0';
					p++;
				}

				nl++;
				len += strlen(p1);

				if(wascr) {
					fl_add_textedit_line(mf->me_text, p1);
					linenum = fl_get_textedit_maxline(mf->me_text) - 1;

					col = 0;
					if(markincl) {
						if(!strncmp(p1, prefix, strlen(prefix)))
							col = markincl;
						else {
							mname = p1;
							i = 0;
							while((*mname != '>') && (i < 4)) {
								if(isalpha(*mname))
									i++;
								else
									if((*mname != ' ')
									   && (*mname != '\t')) break;
								mname++;
							}

							if(*mname == '>')
								col = markincl;
						}
					}

					if(col)
						fl_set_textedit_line_color(mf->me_text, linenum,
												   -1, col);

#ifdef HAVE_REGCOMP
					if(showurl &&
					   ((urls
						 =
						 highlight_urls(fl_get_textedit_line
										(mf->me_text, linenum))) != NULL)) {
						url = urls;
						while(url) {
							fl_set_textedit_blockattr(mf->me_text, linenum,
													  linenum, url->url_s,
													  url->url_e,
													  showurl |
													  ATTR_UNDERLINE);
							url = url->next;
						}

						url = urls;
						while(url) {
							urls = url->next;
							free(url);
							url = urls;
						}
					}
#endif
				} else
					fl_append_to_textedit_line(mf->me_text, -1, p1);

				wascr = p ? 1 : 0;

				if(!p || !*p)
					break;
				p1 = p;
			}
		}

		p = (*mime->encoding->ce_dec) (NULL, &i);
		if(p && (strlen(p) > 1)) {
			if(mime->charset->decode)
				p = (*mime->charset->decode) (p);
			if(p)
				fl_add_textedit_line(mf->me_text, p);
		}

		if(Config.getInt("sheader", 0))
			fl_set_textedit_topline(mf->me_text, headerlines);
	} else {
		mime = get_text_part(msg);

		if(mime && mime->charset &&
		   (mime->charset->charset_code != CHAR_UNKNOWN)) {
			set_menu_chset(mf->me_lang, mime->charset);
			set_menu_enc(mf->me_enc, mime->encoding);
			fl_set_textedit_fontstyle(mf->me_text,
				charset_style_from_code(mime->charset->charset_code));
			fl_set_textedit_fontsize(mf->me_text,
				charset_size_from_code(mime->charset->charset_code));

			fl_set_browser_fontsize(mf->me_mime,
				charset_size_from_code(mime->charset->charset_code));
			fl_set_browser_fontstyle(mf->me_mime,
				charset_style_from_code(mime->charset->charset_code));
		} else {
			set_menu_chset(mf->me_lang, &supp_charsets[DEFAULT_CHARSET]);
			set_menu_enc(mf->me_enc, &supp_encodings[DEFAULT_ENCODING]);
			fl_set_browser_fontsize(mf->me_mime,
				charset_size_from_code(supp_charsets[DEFAULT_CHARSET].charset_code));
			fl_set_textedit_fontsize(mf->me_text,
				charset_size_from_code(supp_charsets[DEFAULT_CHARSET].charset_code));

			fl_set_browser_fontstyle(mf->me_mime,
				charset_style_from_code(supp_charsets[DEFAULT_CHARSET].charset_code));
			fl_set_textedit_fontstyle(mf->me_text,
				charset_style_from_code(supp_charsets[DEFAULT_CHARSET].charset_code));
		}

		if((mime == NULL) || (mime->m_start == mime->m_end)) {
			display_msg(MSG_STAT, NULL, "Edit: Nothing to display");
			return;
		}
#ifndef MMAP_MSG
		if((mfd == NULL) &&
		   (mfd = fopen(msg->get_file(mf->me_msg), "r")) == NULL) {
			display_msg(MSG_WARN, "Can not open message file", "%s",
						msg->get_file(mf->me_msg));
			return;
		}
#else
		msg->free_text(msg);
		if(msg->get_text(msg, mime) != 0) {
			display_msg(MSG_WARN, "edit", "Can not access message");
			return;
		}
#endif

		msg_seek(mfd, mime->m_start, SEEK_SET);

		if(mime->boundary) {
			while(msg_gets(buf, 1024, mfd)) {
				strip_newline(buf);
				if(strlen(buf) < 1)
					break;
			}
		}
#ifndef MMAP_MSG
		if(ferror(mfd) || feof(mfd)) {
			display_msg(MSG_WARN, "EDIT", "Error reading message");
			fclose(mfd);
			return;
		}
#endif

		nl = 0;
		(*mime->encoding->ce_dec) (NULL, &i);

		buf2 = (char*) malloc(sizeof(char));
		if(!buf2) {
			display_msg(MSG_FATAL,"view", "Unable to allocate memory for read buffer");
			return;
		}

		buf2_len++;

		display_msg(MSG_STAT,"view","Reading File In");

		while(((mf->tofft = msg_tell(mfd)) < mime->m_end)
			  && msg_gets(buf,1024,mfd)) {

			ch_got = strlen(buf);
			//fprintf(stderr,"ch_got: %i\n", ch_got);

			while((index + ch_got) > buf2_len) {
				//fprintf(stderr,"%i > %i\n", index+ch_got,buf2_len);
				buf2 = (char*) realloc(buf2,buf2_len + (expgrowth *= 2));
				if(!buf2) {
					display_msg(MSG_FATAL,"view", "Unable to re-allocate memory for read buffer");
					return;
				}
				buf2_len += expgrowth;
				//fprintf(stderr,"buf2 adjusted to %i\n",buf2_len);
			}

			//fprintf(stderr,"Taking %i chars at index %i\n",ch_got,index);
			memcpy(&buf2[index],buf,ch_got);
			index += ch_got;
			//fprintf(stderr,"New Index: %i\n",index);
		}
		buf2[index] = '\0';
		len += index;

		display_msg(MSG_STAT,"view","Encoding Message");
		if((text = (*mime->encoding->ce_dec) (buf2, &buf2_len)) == NULL) {
			display_msg(MSG_WARN, "view", "mime decoding failed on buf2\n");
		}

		free(buf2);

		//fprintf(stderr,"Msg Length: %i\n",strlen(text));
		//fprintf(stderr,"Msg Index: %i\n",index);

		mf->tofft =
		(mf->tofft > mime->m_end) ? 0 : mime->m_end - mf->tofft;

		//fprintf(stderr,"text len: %i\n",strlen(text));
		display_msg(MSG_STAT,"view","Displaying Message");
		if(text) {
			fl_set_textedit(mf->me_text, text, -1);
		}
	}

	fl_set_textedit_cursorpos(mf->me_text, 0, 0, -1, 1);
	fl_set_textedit_bufchanged(mf->me_text, 0);

#ifndef MMAP_MSG
	fclose(mfd);
#else
	msg->free_text(msg);
#endif


	return;

}

char *compose_msg_text(struct msg_form *mf, int update) {
	static char nfile[255];
	struct _mime_msg *mime;
	FILE *mfd, *nfd;
	char buf[255];
	char *ntext, *p;
	int i;

	if(mf->me_flags & MF_READONLY)
		return NULL;

	snprintf(nfile, sizeof(nfile), "%s.mai", get_temp_file("nfile"));
	if((nfd = fopen(nfile, "w")) == NULL) {
		display_msg(MSG_WARN, "Can not open file", "%s", nfile);
		return NULL;
	}

	ntext = (char *) fl_get_textedit(mf->me_text, NULL);
	if((mime = get_text_part(mf->me_msg)) == NULL) {
		if(update && (!ntext || (strlen(ntext) < 1))) {
			free(ntext);
			fclose(nfd);
			return nfile;
		}

		mime = create_mime();
		if(!mime) {
			display_msg(MSG_WARN, "compose text",
						"Can not create MIME text part");
			fclose(nfd);
			free(ntext);
			return NULL;
		}

		mime->encoding = &supp_encodings[def_encoding];
		mime->charset = &supp_charsets[def_charset];
		mime->flags = TEXT_PART;
		mime->mime_next = mf->me_msg->mime;
		mf->me_msg->mime = mime;
	}

	if((mfd = fopen(mf->me_msg->get_file(mf->me_msg), "r")) == NULL) {
		display_msg(MSG_WARN, "Can not open message file", "%s",
					mf->me_msg->get_file(mf->me_msg));
		fclose(nfd);
		fclose(mfd);
		free(ntext);
		return NULL;
	}

	if(ntext && strlen(ntext))
		fputs(ntext, nfd);
	if(ntext)
		free(ntext);

	if((mf->tofft > 0) && ((mime->m_end - mf->tofft) > mime->m_start)) {
		if(fseek(mfd, mime->m_end - mf->tofft, SEEK_SET) == -1) {
			display_msg(MSG_WARN, "edit",
						"Failed to compose message (seek failed)");
			fclose(nfd);
			fclose(mfd);
			return NULL;
		}

		(*mime->encoding->ce_dec) (NULL, &i);
		while((ftell(mfd) < mime->m_end) && fgets(buf, 255, mfd)) {
			if((p = (*mime->encoding->ce_dec) (buf, &i)) != NULL)
				fputs(p, nfd);
		}

		if((p = (*mime->encoding->ce_dec) (NULL, &i)) != NULL)
			fputs(p, nfd);

		fputc('\n', nfd);
	}

	if(ftell(nfd) == 0) {
		if(update) {
			unlink(nfile);
			mime->flags = 0;
		}
	}

	fclose(nfd);
	fclose(mfd);

	mime->src_info = strdup(nfile);
	mime->flags |= FILE_TEMP;

	if(update)
		update_mime(mf->me_msg);

	return nfile;
}
