/* $Id: xfmail.cpp,v 1.47 2004/01/02 04:05:37 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 <xfmail.h>

#include "addrbook_util.h"
#include "tip.h"

static void usage(char *s, int die) {
	char **q = helps;

	fprintf(stderr, "usage: %s: [options] <addrs>...\n", s);
	fprintf(stderr, "  where options are\n");
	for(; *q; q++)
		fprintf(stderr, "   %s\n", *q);

	if(die)
		exit(1);
}

static void
parse_geometry(const char *gstr, int *x, int *y,
			   unsigned int *w, unsigned int *h) {
	int s;
	/* For each value not found, the argument is left unchanged. */
	s = XParseGeometry((char *) gstr, x, y, w, h);
	if(*w < 600)
		*w = 600;
	if(*h < 300)
		*h = 300;
	if((s & XValue) && (s & XNegative))
		*x += fl_scrw - *w;
	if((s & YValue) && (s & YNegative))
		*y += fl_scrh - *h;
}

void abort_button_active(FL_OBJECT * button, int active) {
	FL_OBJECT *obj;

	if(!button)
		return;

	abortbutton = 0;
	if(active)
		fl_activate_form(button->form);
	obj = button->form->first;
	while(obj) {
		if(obj != button) {
			if(active)
				fl_deactivate_object(obj);
			else
				fl_activate_object(obj);
		}
		obj = obj->next;
	}

	if(active)
		fl_activate_object(button);
	else
		fl_deactivate_object(button);
	XFlush(fl_display);

	return;
}

void my_deactivate() {
	fl_deactivate_all_forms();
	abort_button_active(abrt, 1);
	msg_text_activate(1);
}

void my_activate() {
	fl_activate_all_forms();
	abort_button_active(abrt, 0);
	msg_text_activate(0);
}

void set_main_icon(int hm, char *name) {
	XWMHints *xwmh;
	XClassHint classHint;

	if(!main_form || !initdone)
		return;

	if((xwmh = XAllocWMHints()) != NULL) {
		if(hm) {
			xwmh->icon_pixmap = iconPix;
			xwmh->icon_mask = iconPix_sh;
		} else {
			xwmh->icon_pixmap = iconPix_noMail;
			xwmh->icon_mask = iconPix_noMail_sh;
		}

		classHint.res_name = "xfmail";
		classHint.res_class = "XFMail";
		XSetClassHint(fl_display, main_form->window, &classHint);


		xwmh->window_group = main_form->window;
		xwmh->flags = IconPixmapHint | IconMaskHint | WindowGroupHint;
		XSetWMHints(fl_display, main_form->window, xwmh);
		XFree((void *) xwmh);
	}

	if((name != NULL) && (strlen(name) > 1)) {
		fl_set_form_title(main_form, name);
		XSetIconName(fl_display, main_form->window, name);
	}
}

void set_cursor(FL_FORM * form, int cursor) {
	if(form) {
		if(cursor)
			fl_set_cursor(form->window, cursor);
		else
			fl_reset_cursor(form->window);
	}

	return;
}

#if STDC_HEADERS || defined(HAVE_STDARG_H)
int display_msg(int flags, const char *title, const char *fmt, ...)
#else
int display_msg(int flags, char *title, char *fmt, va_list)
#endif
{
	va_list ap;
	char buf[255];
	char buf1[255];
	char errstr[64];
	int mtype = flags & 0x0f, res = 0;

#if STDC_HEADERS || defined(HAVE_STDARG_H)
	va_start(ap, fmt);
#else
	va_start(ap);
#endif

	vsnprintf(buf, sizeof(buf), fmt, ap);

	va_end(ap);

	if((mtype == MSG_FATAL) || (mtype == MSG_WARN) ||
	   (mtype == MSG_STDERR)) {
#ifndef HAVE_STRERROR
		if(errno > 0) {
			sprintf(errstr, "System Error %d", errno);
			errno = 0;
		}
#else
		if(errno > 0) {
			if(strerror(errno))
				strncpy(errstr, strerror(errno), 63);
			else
				sprintf(errstr, "Unknown Error %d", errno);
			errno = 0;
		}
#endif
		else
			strcpy(errstr, "ERROR");
	}

	if(!init)
		mtype = MSG_STDERR;

	switch(mtype) {
		case MSG_FATAL:
			if(supress_errors)
				return 0;

			if(title)
				fl_show_alert(errstr, title, buf, 1);
			else
				fl_show_alert(errstr, buf, "", 1);
			exit(1);
			break;

		case MSG_QUEST:
			if(supress_questions)
				return(flags & MSG_DEFNO) ? 0 : 1;

			if(title) {
				snprintf(buf1, sizeof(buf1), "%s\n\n%s", title, buf);
				res = fl_show_question(buf1, (flags & MSG_DEFNO) ? 0 : 1);
			} else
				res = fl_show_question(buf, (flags & MSG_DEFNO) ? 0 : 1);
			break;

		case MSG_WARN:
			if(title)
				snprintf(buf1, sizeof(buf1), "WARN: %s: %s", title, buf);
			else
				snprintf(buf1, sizeof(buf1), "WARN: %s", buf);

			if(logging & LOG_ERRORS)
				xfm_log_str(buf1);

			if(supress_errors)
				return 0;

			if(title)
				fl_show_alert(errstr, title, buf, 1);
			else
				fl_show_alert(errstr, buf, "", 1);
			break;

		case MSG_MSG:
			if(supress_errors)
				return 0;

			if(title)
				fl_show_message("MESSAGE", title, buf);
			else
				fl_show_message("MESSAGE", buf, "");
			break;

		case MSG_STAT:
			buf[200] = '\0';
			if(status)
				fl_set_object_label(status, buf);
			XFlush(fl_display);
			return 0;
			break;

		case MSG_LOG:
			if(title)
				snprintf(buf1, sizeof(buf1), "%s: %s", title, buf);
			else
				snprintf(buf1, sizeof(buf1), "%s", buf);

			xfm_log_str(buf1);
			XFlush(fl_display);
			return 0;
			break;

		case MSG_STDERR:
			if(title)
				fprintf(stderr, "%s\n%s: %s\n", title, errstr, buf);
			else
				fprintf(stderr, "%s\n%s\n", errstr, buf);
			fflush(stderr);
			return 0;
			break;

		default:
			return -1;
			break;
	}

	XFlush(fl_display);
	fl_check_only_forms();
	return res;
}

#if STDC_HEADERS || defined(HAVE_STDARG_H)
void fl_edit_error(char *fmt, ...)
#else
int fl_edit_error(ffmt, va_list)
#endif
{
	va_list arg;

#if STDC_HEADERS || defined(HAVE_STDARG_H)
	va_start(arg, fmt);
#else
	va_start(arg);
#endif

	display_msg(MSG_WARN, "fl_error", fmt, arg);
	va_end(arg);
}

int idle_cb(XEvent * xev, void *d) {
	check_extprocs();
	return 0;
}

int
fld_posthandler(FL_OBJECT * ob, int event,
				FL_Coord mx, FL_Coord my, int key, void *raw_ev) {
	int num, cw;
	struct _mail_folder *fld;

	switch(event) {
		case FL_PUSH:
			num = fl_get_browser(ob);
			num--;

			if(!(fld = get_folder_by_index(num)))
				break;

			if(!fld->subfold)
				break;

			cw = fl_get_string_width(ob->lstyle, ob->lsize, "+", 1);
			if(mx <= ob->x + ob->bw + cw + 3) {
				expand_collapse_tree(fld, 0);
				if(current_folder && (current_folder->status & FSKIP))
					cb_folders_dbl(ob, 0);
				restore_fld_win();
			}
			break;

		case FL_KEYBOARD:
			switch(key) {
				case XK_F1:
					num = fl_get_browser(ob) - 1;

					if(!(fld = get_folder_by_index(num)))
						break;

					disp_infowindow(fld, INFO_FOLDER);
					break;

				case '\t':
					fl_set_focus_object(main_form, b_messages);
					break;
			}
			break;
	}

	return 0;
}

int
msg_posthandler(FL_OBJECT * ob, int event,
				FL_Coord mx, FL_Coord my, int key, void *raw_ev) {
	int i, num, x, y;
	struct _mail_msg *msg;
	XEvent *xev;

	xev = (XEvent *) raw_ev;

	switch(event) {
		case FL_PUSH:
			num = abs(fl_get_browser(b_messages)) - 1;

			if(xev->xbutton.state & ControlMask) {
				fl_select_browser_line(b_messages, current_index + 1);
				break;
			}

			if(xev->xbutton.state & ShiftMask) {
				if(current_index > num) {
					x = num + 1;
					y = current_index + 1;
				} else {
					x = current_index + 1;
					y = num + 1;
				}
				fl_freeze_form(main_form);
				for(i = x; i <= y; i++)
					fl_select_browser_line(b_messages, i);
				fl_select_browser_line(b_messages, current_index + 1);
				fl_unfreeze_form(main_form);
				break;
			}

			fl_freeze_form(main_form);
			fl_deselect_browser(b_messages);
			set_current_message(get_msg_by_index(current_folder, num), 1);
			fl_unfreeze_form(main_form);

			if((key == 2) && current_message) {
				if(current_folder == draft) {
					set_msg_date(current_message, time(NULL), time(NULL));
					edit_msg(current_message);
				} else if(current_folder == mftemplate)
					template_msg(current_message);
				else
					view_msg(current_message, 0);
			} else if((key == 3) && current_message) {
				fl_select_browser_line(b_messages, current_index + 1);
				fl_dopup(mpup);
			}

			break;

		case FL_KEYBOARD:
			switch(key) {
				case XK_F1:
					disp_infowindow(current_message, INFO_MSG);
					break;

				case XK_Up:
					if(current_index == 0)
						break;

					num = current_index - 1;
					if((msg = get_msg_by_index(current_folder, num)) == NULL)
						break;

					fl_freeze_form(main_form);
					set_current_message(msg, 1);
					fl_unfreeze_form(main_form);
					break;

				case XK_Down:
					if(!current_message || !current_message->next)
						break;

					num = current_index + 1;
					if((msg = get_msg_by_index(current_folder, num)) == NULL)
						break;

					fl_freeze_form(main_form);
					set_current_message(msg, 1);
					fl_unfreeze_form(main_form);
					break;

				case '\t':
					fl_set_focus_object(main_form, b_folders);
					break;
			}
			break;
	}

	return 0;
}

int
preemptive_handler(FL_OBJECT * ob, int event,
				   FL_Coord mx, FL_Coord my, int key, void *raw_ev) {
	static int l = -1;
	static int dragndrop = 0;
	FL_OBJECT *obj;
	int lh, t;
	int tx, ty, tw, th;
	XEvent *xev;

	xev = (XEvent *) raw_ev;

	if(!fl_get_browser_maxline(ob))
		return !FL_PREEMPT;

	switch(event) {
		case FL_PUSH:
			if((key == 2) || (key == 3)) {
				dragndrop = -1;
				return !FL_PREEMPT;
			}
			break;

		case FL_MOUSE:
			obj = fl_find_first(main_form, FL_FIND_MOUSE, mx, my);

			switch(dragndrop) {
				case -1:
					break;

				case 0:
					if(obj != b_folders)
						return !FL_PREEMPT;
					dragndrop = 2;
					fl_select_browser_line(b_messages, current_index + 1);
					if(xev->xbutton.state & ShiftMask)
						set_cursor(main_form, XC_exchange);
					else
						set_cursor(main_form, mailcur);
					return FL_PREEMPT;
					break;

				case 1:
					if(obj == b_folders) {
						dragndrop = 2;
						if(xev->xbutton.state & ShiftMask)
							set_cursor(main_form, XC_exchange);
						else
							set_cursor(main_form, mailcur);
					}

					return FL_PREEMPT;
					break;

				case 2:
					if(obj != b_folders) {
						dragndrop = 1;
						set_cursor(main_form, XC_cross);
					} else {
						/* XXX: We should take the dimensions of
						 * b_folders here, not 'ob' the message
						 * browser window. However, if we do Xforms
						 * doesn't repaint the folder browser
						 * correctly. Therefore, we pretend that the
						 * height of the message browser is the same
						 * as the folder browser, but this is not
						 * always the case. If the preview window is
						 * open, then our calculations will be way off
						 * and the situation is hopeless.
						 *
						 * Need to investigate why Xforms doesn't
						 * repaint correctly.
						 */
						 
						fl_get_browser_dimension(ob, &tx, &ty, &tw, &th);
						lh = th / fl_get_browser_screenlines(ob);
						t = fl_get_browser_topline(b_folders);
						l = my - ty;
						if(l <= 0) {
							/* Move browser up one line if possible. */
							if (t > 1)
								fl_set_browser_topline(b_folders, --t);
							l = 0;
						}

						l = l / lh;
						if(l >= fl_get_browser_screenlines(b_folders)) {
							/* Move browser down one line if possible */
							if (t + fl_get_browser_screenlines(b_folders) <=
								fl_get_browser_maxline(b_folders))
								fl_set_browser_topline(b_folders, ++t);
							l = fl_get_browser_screenlines(b_folders) - 1;
						}
						/* Make sure we don't attempt to select a line
						 * greater than what the browser contains. This
						 * can happen when the browser window is larger
						 * then the number of entries (ie., no scroll bar).
						 */
						if (t + l > fl_get_browser_maxline(b_folders))
							l = fl_get_browser_maxline(b_folders) - t;
						fl_select_browser_line(b_folders, t + l);
					}

					return FL_PREEMPT;
					break;
			}
			break;
		case FL_RELEASE:
			switch(dragndrop) {
				case -1:
					break;

				case 0:
					fl_select_browser_line(b_messages, current_index + 1);
					return !FL_PREEMPT;
					break;

				case 1:
					set_cursor(main_form, 0);
					fl_ringbell(100);
					break;

				case 2:
					set_cursor(main_form, 0);
					if(l < 0)
						fl_ringbell(100);
					else {
						l = l + fl_get_browser_topline(b_folders) - 1;
						if(l >= (int)mailbox.size())
							fl_ringbell(100);
						else {
							if(xev->xbutton.state & ShiftMask)
								copy_messages(get_folder_by_index(l));
							else
								move_messages(get_folder_by_index(l));
						}
					}
					break;
			}
			dragndrop = 0;
			l = -1;
			break;
	}

	return !FL_PREEMPT;
}

int get_fld_color(struct _mail_folder *fld) {
	int color;

	color = color_fld[FLD_NORMAL_CLR];
	if(fld->color != -1)
		color = fld->color;
	else if(fld->status & FDUMMY)
		color = color_fld[FLD_DUMMY_CLR];
	else if(fld->status & SEARCH)
		color = color_fld[FLD_SEARCH_CLR];
	else if((fld->flags & FMARKED) || (fld->status & FMRKTMP))
		color = color_fld[FLD_MARK_CLR];
	else if(fld->status & FRECNT)
		color = color_fld[FLD_RECENT_CLR];
	else if(fld->status & SYSTEM)
		color = color_fld[FLD_SYSTEM_CLR];
	else if(fld->type & F_IMAP)
		color = color_fld[FLD_IMAP_CLR];
	else if(fld->type & F_NEWS)
		color = color_fld[FLD_NEWS_CLR];

	return color;
}

char *get_fld_line(struct _mail_folder *fld) {
	static char fldline[64];
	int color =
	(fld ==
	 current_folder) ? color_fld[FLD_CURR_CLR] : get_fld_color(fld);
	char tchar = ' ';

	if(fld->subfold)
		tchar = (fld->flags & FEXPND) ? '-' : '+';

	if(fld->status & FDUMMY)
		snprintf(fldline, sizeof(fldline), "@C%d%c%-.*s%-*.*s", color,
				 tchar, fld->level, "           ", show_fld[FOLD_LEN],
				 show_fld[FOLD_LEN], fld->sname);
	else
		snprintf(fldline, sizeof(fldline), "@C%d%c%-.*s%-*.*s%*lu%*lu",
				 color, tchar, fld->level, "           ",
				 show_fld[FOLD_LEN], show_fld[FOLD_LEN], fld->sname,
				 show_fld[FNUM_LEN], fld->num_msg, show_fld[FUNR_LEN],
				 fld->unread_num);

	return fldline;
}

char *get_msg_line(struct _mail_msg *msg) {
	static char msgline[255];
	struct _head_field *fld;
	u_long mlen;
	char tbuf[19], size[6], mstat[5], subj[128], msguid[16], *addrline,
	*apref = "";
	int color, ftype, fromlen = show_msg[FROM_LEN];

	mstat[0] = size[0] = tbuf[0] = msguid[0] = '\0';
	color = color_msg[MSG_NORMAL_CLR];
	ftype = -1;

	if(msg == current_message)
		color = color_msg[MSG_CURR_CLR];

	if(show_msg[STAT_LEN]) {
		mstat[2] = '\0';
		mstat[0] = mstat[1] = ' ';
		if(msg->status & LOCKED)
			mstat[0] = 'L';
		else if(msg->status & MTOUS)
			mstat[0] = '+';
		else if(msg->flags & UNREAD)
			mstat[0] = 'N';
		else if(msg->flags & M_SFAILED)
			color = 5;

		if(msg->flags & UNREAD)
			color = color_msg[MSG_UNREAD_CLR];

		if((msg->flags & MARKED) || (msg->status & MARKTMP)) {
			if(color == 0)
				color = color_msg[MSG_MARK_CLR];
			mstat[0] = '*';
		}

		if(msg->status & MOVED)
			mstat[0] = 'M';
		else if(msg->status & DELETED) {
			mstat[0] = 'D';
			color = color_msg[MSG_DELETED_CLR];
		}

		if(msg->flags & ANSWERED)
			mstat[1] = 'A';
		else if(msg->flags & FORWARDED)
			mstat[1] = 'F';
		else if((msg->flags & PGP_SIGNED) || (msg->flags & PGP_ENCRYPTED))
			mstat[1] = 'P';
		else if(msg->flags & URGENT2)
			mstat[1] = '!';
		else if(is_mime_msg(msg))
			mstat[1] = 'M';
		else if(msg->flags & H_ONLY)
			mstat[1] = '/';
	}

	if(show_msg[DATE_LEN])
		strftime(tbuf, 19, "%h-%d %H:%M %Y ",
				 localtime(&msg->header->snt_time));

	if(show_msg[SIZE_LEN]) {
		if((msg->flags & H_ONLY) &&
		   (fld = find_field(msg, MIME_C_LENGTH)))
			mlen = atol(fld->f_line);
		else
			mlen = msg->msg_len;

		if(mlen >= 1000000)
			sprintf(size, "%.1fM ", (float) mlen / 1024 / 1024);
		else if(mlen >= 10000)
			sprintf(size, "%dK ", (int) (mlen / 1024));
		else
			sprintf(size, "%d ", (int) mlen);
	}

	if(show_msg[UID_LEN]) {
		sprintf(msguid, "%ld", msg->real_uid);
	}

	strncpy(subj,
			msg->header->Subject ? rfc1522_decode(msg->header->Subject,
												  &ftype) : "", 127);
	subj[127] = '\0';
	if(fromlen && ((current_folder->flags & FSHRECP) ||
				   (msg->status & MFROMUS))) {
		addrline = msg->header->To ? get_short_addr_line(msg->header->To) :
				   (msg->header->News ? msg->header->News->name : const_cast<char*>(""));
		apref =
		msg->header->To ? const_cast <
		char *>("To: ") : (msg->header->News ? const_cast <
						   char *>("Nn: ") : const_cast < char *>(""));
		fromlen -= strlen(apref);
		if(fromlen <= 0) {
			fromlen = show_msg[FROM_LEN];
			apref = "";
		}
	} else
		addrline = get_short_addr_line(msg->header->From);

	if(msg->status & S_THREAD)
		snprintf(msgline, sizeof(msgline),
				 "@C%d %*.*s %*.*s%*s %-*.*s%-*.*s%s%-*.*s %s", color,
				 show_msg[UID_LEN], show_msg[UID_LEN], msguid, msg->refs,
				 show_msg[SUBJ_LEN], "", show_msg[STAT_LEN], mstat,
				 show_msg[DATE_LEN], show_msg[DATE_LEN], tbuf,
				 show_msg[SIZE_LEN], show_msg[SIZE_LEN], size, apref,
				 fromlen, fromlen, addrline, subj);
	else
		snprintf(msgline, sizeof(msgline),
				 "@C%d %*.*s %*s %-*.*s%-*.*s%s%-*.*s %s", color,
				 show_msg[UID_LEN], show_msg[UID_LEN], msguid,
				 show_msg[STAT_LEN], mstat, show_msg[DATE_LEN],
				 show_msg[DATE_LEN], tbuf, show_msg[SIZE_LEN],
				 show_msg[SIZE_LEN], size, apref, fromlen, fromlen,
				 addrline, subj);


	return msgline;
}

void display_fld_status(struct _mail_folder *fld) {
	char ftype[64], flags[64];

	strcpy(ftype, "MH");
	flags[0] = '\0';
	flags[1] = '\0';

	if(fld == NULL)
		return;

	if(fld->type & F_IMAP) {
		struct _imap_src *imap = (struct _imap_src *) fld->spec;
		snprintf(ftype, sizeof(ftype), "IMAP [%s]", imap->name);
	} else if(fld->type & F_NEWS)
		strcpy(ftype, "NEWS");
	else if(fld->type & F_MBOX)
		strcpy(ftype, "MBOX");

	if(fld->status & FRONLY)
		strcat(flags, " READ-ONLY");

	if(fld->status & SYSTEM)
		strcat(flags, " SYSTEM");

	if(fld->flags & CACHED)
		strcat(flags, " CACHED");

	if(fld->status & NOTRASH)
		strcat(flags, " TRASH");

	flags[0] = '(';

	if(fld->descr)
		display_msg(MSG_STAT, NULL,
					"%-.64s (%-.64s): Type: %s Flags: %s) Messages: %d Unread: %d",
					fld->fold_path, fld->descr, ftype, flags, fld->num_msg,
					fld->unread_num);
	else
		display_msg(MSG_STAT, NULL,
					"%-.64s: Type: %s Flags: %s) Messages: %d Unread: %d",
					fld->fold_path, ftype, flags, fld->num_msg,
					fld->unread_num);
}

void redraw_fld(struct _mail_folder *fld) {
	if(!fld || !b_folders)
		return;

	if((fld->status & FHIDDN) || (fld->status & FSKIP))
		return;

	fld->status &= ~FRESCAN;
	if(!(folder_sort & FLD_SORTED)) {
		sort_folders();
		redraw_fld_win();
		return;
	}

	fl_replace_browser_line(b_folders, get_folder_index(fld) + 1,
							get_fld_line(fld));
	if(fld == current_folder)
		redraw_msg_win();

	display_fld_status(fld);
}

void redraw_fld_line(struct _mail_folder *fld) {
	if(fld->status & FSKIP)
		return;

	if(!b_folders || !menu_folders)
		return;

	if(fld && !(fld->status & FHIDDN)) {
		fl_replace_browser_line(b_folders, get_folder_index(fld) + 1,
								get_fld_line(fld));
		if(fld == current_folder) {
			fl_set_menu_item_mode(menu_folders, 2,
								  (current_folder->
								   status & NOINFR) ? FL_PUP_GRAY :
								  FL_PUP_NONE);
			fl_set_menu_item_mode(menu_folders, 3,
								  (current_folder->
								   status & SYSTEM) ? FL_PUP_GRAY :
								  FL_PUP_NONE);
			fl_set_menu_item_mode(menu_folders, 4,
								  (current_folder->
								   status & SYSTEM) ? FL_PUP_GRAY :
								  FL_PUP_NONE);
		}
	}
}

void redraw_msg(struct _mail_msg *msg) {
	int mindex = get_msg_index(current_folder, msg) + 1;

	if(!msg || !b_messages)
		return;

	if(msg->folder != current_folder)
		return;

	fl_replace_browser_line(b_messages, mindex, get_msg_line(msg));

	if(msg == current_message)
		fl_select_browser_line(b_messages, mindex);

	msg->status &= ~MREFRESH;

	return;
}

void refresh_msgs() {
	struct _mail_msg *msg = current_folder->messages;
	int hascurrent = 0;

	while(msg) {
		if(msg->status & MREFRESH)
			redraw_msg(msg);
		if(msg == current_message)
			hascurrent = 1;
		msg = msg->next;
	}

	if(!hascurrent) {
		current_message = current_folder->messages;
		current_index = 0;
		if(current_folder->status & FRESCAN)
			redraw_fld_line(current_folder);
		redraw_msg_win();
	} else {
		if(current_folder->status & FRESCAN) {
			redraw_fld_line(current_folder);
			restore_msg_win();
			return;
		}
	}
}

void redraw_fld_win() {
	int i;

	if(!main_form)
		return;

	fl_freeze_form(main_form);
	fl_clear_browser(b_folders);

	if(!(folder_sort & FLD_SORTED))
		sort_folders();

	for(i = 0; i < (int)mailbox.size(); i++) {
		if(mailbox[i]->status & FSKIP)
			continue;
		fl_add_browser_line(b_folders, get_fld_line(mailbox[i]));
	}

	fl_select_browser_line(b_folders,
						   get_folder_index(current_folder) + 1);
	fl_show_browser_line(b_folders, get_folder_index(current_folder) + 1);

	if(current_folder && (current_folder->status & SYSTEM))
		i = FL_PUP_GRAY;
	else
		i = FL_PUP_NONE;

	fl_set_menu_item_mode(menu_folders, 2,
						  (current_folder
						   && (current_folder->
							   status & NOINFR)) ? FL_PUP_GRAY :
						  FL_PUP_NONE);
	fl_set_menu_item_mode(menu_folders, 3, i);
	fl_set_menu_item_mode(menu_folders, 4, i);

	display_fld_status(current_folder);

	fl_unfreeze_form(main_form);
}

void restore_fld_win() {
	int i, k;

	if(!main_form)
		return;

	fl_freeze_form(main_form);
	k = fl_get_browser_topline(b_folders);
	fl_clear_browser(b_folders);
	for(i = 0; i < (int)mailbox.size(); i++) {
		if(mailbox[i]->status & FSKIP)
			continue;
		fl_add_browser_line(b_folders, get_fld_line(mailbox[i]));
	}
	fl_select_browser_line(b_folders,
						   get_folder_index(current_folder) + 1);
	fl_set_browser_topline(b_folders, k);
	fl_unfreeze_form(main_form);
}

void restore_msg_win() {
	struct _mail_msg *msg;
	int i, hascurmsg = 0;

	if(!main_form)
		return;

	if(!(current_folder->status & SORTED))
		sort_folder(current_folder);

	i = fl_get_browser_topline(b_messages);
	fl_freeze_form(main_form);
	fl_clear_browser(b_messages);

	msg = current_folder->messages;
	while(msg) {
		fl_add_browser_line(b_messages, get_msg_line(msg));
		msg->status &= ~MREFRESH;
		if(msg == current_message)
			hascurmsg = 1;
		msg = msg->next;
	}

	if(hascurmsg) {
		current_index = get_msg_index(current_folder, current_message);
		fl_select_browser_line(b_messages, current_index + 1);
	} else {
		current_message = NULL;
		set_current_message(current_folder->messages, 0);
		fl_select_browser_line(b_messages, 1);
	}

	fl_set_browser_topline(b_messages, i);
	fl_unfreeze_form(main_form);
	display_fld_status(current_folder);
	current_folder->status &= ~FRESCAN;
}

void redraw_msg_win() {
	struct _mail_msg *msg;
	int hascurmsg = 0;

	if(!main_form)
		return;

	fl_freeze_form(main_form);
	fl_clear_browser(b_messages);

	if(!(current_folder->status & SORTED))
		sort_folder(current_folder);

	msg = current_folder->messages;
	while(msg) {
		fl_add_browser_line(b_messages, get_msg_line(msg));
		if(msg == current_message)
			hascurmsg = 1;
		msg->status &= ~MREFRESH;
		msg = msg->next;
	}

	if(!hascurmsg) {
		current_message = NULL;
		set_current_message(current_folder->messages, 0);
	} else
		current_index = get_msg_index(current_folder, current_message);

	fl_select_browser_line(b_messages, current_index + 1);
	fl_show_browser_line(b_messages, current_index + 1);
	fl_unfreeze_form(main_form);
	display_fld_status(current_folder);
	current_folder->status &= ~FRESCAN;
}

void refresh_folders() {
	int i;

	for(i = 0; i < (int)mailbox.size(); i++) {
		if(mailbox[i]->status & FSKIP)
			continue;
		if(mailbox[i]->status & FRESCAN)
			redraw_fld(mailbox[i]);
		mailbox[i]->status &= ~FRESCAN;
	}

	return;
}

void redraw_folders() {
	struct _mail_msg *msg;
	int i, hascurmsg = 0;

	if(!main_form)
		return;

	fl_freeze_form(main_form);
	fl_clear_browser(b_folders);

	if(!(folder_sort & FLD_SORTED))
		sort_folders();

	for(i = 0; i < (int)mailbox.size(); i++) {
		if(mailbox[i]->status & FSKIP)
			continue;
		fl_add_browser_line(b_folders, get_fld_line(mailbox[i]));
		mailbox[i]->status &= ~FRESCAN;
	}

	fl_select_browser_line(b_folders,
						   get_folder_index(current_folder) + 1);
	fl_show_browser_line(b_folders, get_folder_index(current_folder) + 1);

	if(current_folder->status & SYSTEM)
		i = FL_PUP_GRAY;
	else
		i = FL_PUP_NONE;

	fl_set_menu_item_mode(menu_folders, 2,
						  (current_folder->
						   status & NOINFR) ? FL_PUP_GRAY : FL_PUP_NONE);
	fl_set_menu_item_mode(menu_folders, 3, i);
	fl_set_menu_item_mode(menu_folders, 4, i);

	fl_clear_browser(b_messages);

	if(!(current_folder->status & SORTED))
		sort_folder(current_folder);

	msg = current_folder->messages;
	while(msg) {
		fl_add_browser_line(b_messages, get_msg_line(msg));
		if(msg == current_message)
			hascurmsg = 1;
		msg = msg->next;
	}

	if(!hascurmsg) {
		current_message = NULL;
		set_current_message(current_folder->messages, 0);
	}

	display_fld_status(current_folder);
	fl_select_browser_line(b_messages, current_index + 1);
	fl_show_browser_line(b_messages, current_index + 1);
	fl_unfreeze_form(main_form);
}

void set_current_folder(struct _mail_folder *folder) {
	struct _mail_folder *ofold = current_folder;

	if(!folder || (folder == current_folder))
		return;

	if(current_folder)
		current_folder->close(current_folder);

	current_folder = folder;
	if(!(current_folder->status & OPENED)) {
		current_folder->open(current_folder, 0);
		mark_to_us(current_folder);
	}

	if((current_folder->status & FSKIP) && current_folder->pfold) {
		expand_tree(const_cast<struct _mail_folder *>(get_ancestor(current_folder)), 1);
		redraw_fld_win();
	}

	if(ofold)
		redraw_fld_line(ofold);
	redraw_fld_line(current_folder);
	fl_deselect_browser_line(b_folders, get_folder_index(ofold) + 1);
	fl_select_browser_line(b_folders,
						   get_folder_index(current_folder) + 1);
	fl_show_browser_line(b_folders, get_folder_index(current_folder) + 1);
	current_index = 0;
	current_message = folder->messages;
	msg_preview(current_message);
	redraw_msg_win();

	return;
}

void set_current_message(struct _mail_msg *msg, int draw) {
	struct _mail_folder *ofold = current_folder;
	struct _mail_msg *omsg = current_message;

	if(main_form == NULL)
		return;

	if(msg == NULL) {
		if(draw)
			fl_deselect_browser_line(b_folders, current_index);
		current_message = current_folder->messages;
		current_index = 0;
		if(draw)
			fl_select_browser_line(b_folders, current_index);
		msg_preview(current_message);
		return;
	}

	if(msg == current_message)
		return;

	if(msg->folder != current_folder) {
		current_folder->close(current_folder);
		current_folder = msg->folder;
		if(!(current_folder->status & OPENED)) {
			current_folder->open(current_folder, 0);
			mark_to_us(current_folder);
		}

		redraw_fld_line(ofold);
		redraw_fld_line(current_folder);
		fl_deselect_browser_line(b_folders, get_folder_index(ofold) + 1);
		fl_select_browser_line(b_folders,
							   get_folder_index(current_folder) + 1);
		fl_show_browser_line(b_folders,
							 get_folder_index(current_folder) + 1);
		redraw_msg_win();
		current_index = 0;
	}

	if((current_folder->status & FSKIP) && current_folder->pfold) {
		expand_tree(const_cast<struct _mail_folder *>(get_ancestor(current_folder)), 1);
		redraw_fld_win();
	}

	if(draw)
		fl_deselect_browser_line(b_messages, current_index + 1);
	current_message = msg;
	current_index = get_msg_index(current_folder, current_message);
	if(draw) {
		redraw_msg(omsg);
		redraw_msg(current_message);
		fl_select_browser_line(b_messages, current_index + 1);
	}
	fl_show_browser_line(b_messages, current_index + 1);
	display_msg(MSG_STAT, NULL, "From: %.64s Subject: %s",
				get_full_addr_line(current_message->header->From),
				current_message->header->Subject ? current_message->
				header->Subject : "* No Subject *");

	msg_preview(current_message);

	return;
}

struct _mail_msg *delete_msg(struct _mail_msg *msg) {
	struct _mail_folder *old_folder;
	int i;

	if(!msg)
		return NULL;

	if(!(msg->status & LOCKED)) {
		old_folder = msg->folder;
		current_index = get_msg_index(msg->folder, msg);
		msg->status |= DELETED;
		old_folder->update(old_folder);
		msg = get_msg_by_index(old_folder, current_index);
		while(msg && ((msg->status & LOCKED) ||
					  (msg->status & DELETED) ||
					  (msg->status & MNOTEXISTS))) msg = msg->next;

		set_current_message(msg, 0);

		for(i = 0; i < (int)mailbox.size(); i++) {
			if(mailbox[i]->status & FSKIP)
				continue;
			if(mailbox[i]->status & NOTRASH) {
				redraw_fld_line(mailbox[i]);
				if(current_folder == mailbox[i])
					restore_msg_win();
			}
		}

		redraw_fld_line(old_folder);
		if(old_folder == current_folder)
			restore_msg_win();

		return msg;
	}
	return msg;
}

struct _mail_msg *next_msg(int ur, struct _mail_msg *cmsg) {
	struct _mail_msg *msg;
	struct _mime_msg *mime;

	if(!cmsg)
		return NULL;

	if(cmsg->data == MSG_DAT_ENCAP) {
		if(ur || (cmsg->pdata == NULL))
			return NULL;

		msg = (struct _mail_msg *) cmsg->pdata;
		mime = msg->mime;
		while(mime) {
			if(mime->flags & LOCK_PART) {
				mime = mime->mime_next;
				if(mime == NULL)
					return NULL;
				msg = get_mime_msg(msg, mime);
				return msg;
			}
			mime = mime->mime_next;
		}
		return NULL;
	}

	msg = cmsg->next;

	if(ur) {
		while(msg) {
			if((msg->flags & UNREAD) &&
			   !(msg->status & LOCKED) &&
			   !(msg->status & MNOTEXISTS) && !(msg->status & DELETED)) {
				set_current_message(msg, 1);
				return msg;
			}
			msg = msg->next;
		}

		if(!get_total_unread() ||
		   !Config.getInt("switchfold", 1)) 
				return NULL;

		if((msg = get_unread_msg()) == NULL)
			return NULL;

		set_current_message(msg, 1);
		return msg;
	} else {
		while(msg) {
			if(!(msg->status & LOCKED) &&
			   !(msg->status & DELETED) && !(msg->status & MNOTEXISTS)) {
				set_current_message(msg, 1);
				return msg;
			}
			msg = msg->next;
		}
		return NULL;
	}

	return NULL;
}

struct _mail_msg *prev_msg(int ur, struct _mail_msg *cmsg) {
	struct _mail_msg *msg;
	struct _mime_msg *mime;
	int i, index;

	if(!cmsg)
		return NULL;

	if(cmsg->data == MSG_DAT_ENCAP) {
		if(ur || (cmsg->pdata == NULL))
			return NULL;

		msg = (struct _mail_msg *) cmsg->pdata;
		mime = msg->mime;
		while(mime && mime->mime_next) {
			if(mime->mime_next->flags & LOCK_PART) {
				msg = get_mime_msg(msg, mime);
				return msg;
			}
			mime = mime->mime_next;
		}
		return NULL;
	}

	msg = NULL;
	index = get_msg_index(cmsg->folder, cmsg);

	for(i = index - 1; i >= 0; i--) {
		msg = get_msg_by_index(cmsg->folder, i);
		if(!msg)
			break;

		if(ur) {
			if((msg->flags & UNREAD) &&
			   !(msg->status & DELETED) &&
			   !(msg->status & MNOTEXISTS) && !(msg->status & LOCKED))
				break;
		} else {
			if(!(msg->status & LOCKED) &&
			   !(msg->status & DELETED) && !(msg->status & MNOTEXISTS))
				break;
		}
	}

	if(i < 0)
		msg = NULL;

	if(!msg && ur) {
		if(!get_total_unread() ||
		   !Config.getInt("switchfold", 1)) 
				return NULL;

		msg = get_unread_msg();
	}

	if(msg)
		set_current_message(msg, 1);

	return msg;
}

int send_msg(struct _mail_msg *msg, int queue) {
	struct _mail_folder *fld;
	int oldoffline = 0, setc = 0;

	fld = msg->folder;

	if(msg == current_message)
		setc = 1;

	if(queue) {
		oldoffline = offline;
		offline = 1;
	}

	if(send_message(msg) == -1) {
		display_msg(MSG_WARN, "send", "Failed to send");
		if(queue)
			offline = oldoffline;
		return -1;
	}

	if(queue)
		offline = oldoffline;

	if(setc) {
		current_message = NULL;
		set_current_message(current_folder->messages, 1);
	}

	refresh_folders();
	redraw_fld(outbox);
	redraw_fld(sentm);
	return 0;
}

int send_pup_cb(int i) {
	cb_menu_send(NULL, i);
	return 100;
}

int mesg_pup_cb(int i) {
	if(i == 100)
		return i;

	cb_menu_messages(NULL, i);
	return i;
}

int fold_pup_cb(int i) {
	cb_menu_folders(NULL, i);
	return i;
}

void cb_fbutton(FL_OBJECT * obj, long arg) {
}

void cb_mbutton(FL_OBJECT * obj, long arg) {
}

int
cb_mbutton_handler(FL_OBJECT * ob, int event, FL_Coord mx, FL_Coord my,
				   int key, void *xev) {
	static int msgpanesz = -1;
	int mdelta, tmy;

	switch(event) {
		case FL_PUSH:
			if((key != 1) || (msgpane == NULL))
				return 0;

			msgpanesz = my - b_messages->y;
			
			set_cursor(main_form, XC_sb_v_double_arrow);
			fl_drawmode(GXxor);
			fl_line(m_button->x, my, m_button->x + m_button->w, my, FL_WHITE);
			fl_line(m_button->x, my - 1, m_button->x + m_button->w, my - 1,
					FL_WHITE);
			fl_line(m_button->x, my + 1, m_button->x + m_button->w, my + 1,
					FL_WHITE);
			fl_drawmode(GXcopy);
			break;

		case FL_RELEASE:
			if((key != 1) || (msgpane == NULL) || (msgpanesz == -1))
				return 0;
			set_cursor(main_form, 0);
		msgpanesz = msgpane->h + b_messages->h +2 - msgpanesz;
			if((msgpanesz != msgpanesize) && (msgpanesz >= 30)
			   && (msgpanesz <= 800)) {
				mdelta = msgpanesize - msgpanesz;
				fl_set_object_size(b_messages, b_messages->w, b_messages->h + mdelta);
				fl_set_object_geometry(msgpane, msgpane->x, msgpane->y + mdelta, msgpane->w, msgpane->h - mdelta);
				fl_set_object_position(m_button, m_button->x, m_button->y + mdelta);
				msgpanesize = msgpanesz;
				Config.set("msgpane", msgpanesize);
			}
			msgpanesz = -1;
			break;

		case FL_MOUSE:
			if((key != 1) || (msgpane == NULL))
				return 0;

			fl_drawmode(GXxor);
			if(msgpanesz != -1) {
		tmy = msgpanesz + b_messages->y;
				fl_line(m_button->x, tmy, m_button->x + m_button->w, tmy,
						FL_WHITE);
				fl_line(m_button->x, tmy - 1, m_button->x + m_button->w,
						tmy - 1, FL_WHITE);
				fl_line(m_button->x, tmy + 1, m_button->x + m_button->w,
						tmy + 1, FL_WHITE);
			}

			if((mx < msgpane->x) || (mx > msgpane->x + msgpane->w)) {
				fl_drawmode(GXcopy);
				set_cursor(main_form, 0);
				msgpanesz = -1;
				break;
			}

			if(((my - b_messages->y) < 30 ) || ((msgpane->h - my + msgpane->y) < 30)) {
				fl_drawmode(GXcopy);
				set_cursor(main_form, 0);
				msgpanesz = -1;
				break;
			}

			if(msgpanesz == -1)
				set_cursor(main_form, XC_sb_v_double_arrow);

		msgpanesz = my - b_messages->y;
			fl_line(m_button->x, my, m_button->x + m_button->w, my, FL_WHITE);
			fl_line(m_button->x, my - 1, m_button->x + m_button->w, my - 1,
					FL_WHITE);
			fl_line(m_button->x, my + 1, m_button->x + m_button->w, my + 1,
					FL_WHITE);
			fl_drawmode(GXcopy);
			break;

		case FL_ENTER:
			set_cursor(main_form, XC_sb_v_double_arrow);
			break;

		case FL_LEAVE:
			set_cursor(main_form, 0);
			break;
	}

	return 0;
}

int
cb_fbutton_handler(FL_OBJECT * ob, int event, FL_Coord mx, FL_Coord my,
				   int key, void *xev) {
	static int fbrowser = -1;
	int tmx;

	switch(event) {
		case FL_PUSH:
			if(key != 1)
				return 0;
			fbrowser = fbrowsersize;
			set_cursor(main_form, XC_sb_h_double_arrow);
			fl_drawmode(GXxor);
			fl_line(mx, f_button->y, mx, f_button->y + f_button->h, FL_WHITE);
			fl_line(mx - 1, f_button->y, mx - 1, f_button->y + f_button->h,
					FL_WHITE);
			fl_line(mx + 1, f_button->y, mx + 1, f_button->y + f_button->h,
					FL_WHITE);
			fl_drawmode(GXcopy);
			break;

		case FL_RELEASE:
			if(key != 1)
				return 0;
			set_cursor(main_form, 0);
			if((fbrowser != fbrowsersize) && (fbrowser >= 80)
			   && (fbrowser <= 300)) {
				fl_set_object_size(b_folders, fbrowser, b_folders->h);
				fl_set_object_geometry(b_messages, 5 + fbrowser, b_messages->y,
									   main_form->w - fbrowser - 8,
									   b_messages->h);
		if(msgpane != NULL) {
			fl_set_object_geometry(msgpane, 5 + fbrowser, msgpane->y,
					main_form->w - fbrowser - 8, msgpane->h);
			fl_set_object_geometry(m_button, 5 + fbrowser, m_button->y,
					 main_form->w -fbrowser -8, m_button->h);
		} 		
				fl_set_object_position(f_button, 3 + fbrowser, f_button->y);

				fbrowsersize = fbrowser;
				Config.set("fbrowser", fbrowsersize);
			}
			fbrowser = -1;
			break;

		case FL_MOUSE:
			if(key != 1)
				return 0;

			fl_drawmode(GXxor);
			if(fbrowser != -1) {
				tmx = fbrowser + b_folders->x;
				fl_line(tmx, f_button->y, tmx, f_button->y + f_button->h,
						FL_WHITE);
				fl_line(tmx - 1, f_button->y, tmx - 1,
						f_button->y + f_button->h, FL_WHITE);
				fl_line(tmx + 1, f_button->y, tmx + 1,
						f_button->y + f_button->h, FL_WHITE);
			}

			if((my < b_folders->y) || (my > b_folders->y + b_folders->h)) {
				fl_drawmode(GXcopy);
				set_cursor(main_form, 0);
				fbrowser = -1;
				break;
			}

			if(((mx - b_folders->x) < 80) || ((mx - b_folders->x) > 300)) {
				fl_drawmode(GXcopy);
				set_cursor(main_form, 0);
				fbrowser = -1;
				break;
			}

			if(fbrowser == -1)
				set_cursor(main_form, XC_sb_h_double_arrow);

			fbrowser = mx - b_folders->x;
			fl_line(mx, f_button->y, mx, f_button->y + f_button->h, FL_WHITE);
			fl_line(mx - 1, f_button->y, mx - 1, f_button->y + f_button->h,
					FL_WHITE);
			fl_line(mx + 1, f_button->y, mx + 1, f_button->y + f_button->h,
					FL_WHITE);
			fl_drawmode(GXcopy);
			break;

		case FL_ENTER:
			set_cursor(main_form, XC_sb_h_double_arrow);
			break;

		case FL_LEAVE:
			set_cursor(main_form, 0);
			break;
	}

	return 0;
}

void template_msg(struct _mail_msg *msg) {
	struct _mail_msg *msg1;

	if(!display_msg
	   (MSG_QUEST, "Template", "Create new message from template?"))
		return;

	msg->status |= LOCKED;
	if(!(msg1 = outbox->copy(current_message, outbox))) {
		display_msg(MSG_WARN, "template", "Can not copy message");
		return;
	}

	msg->status &= ~LOCKED;
	msg1->status &= ~LOCKED;
	msg1->status |= MSGNEW;
	set_msg_date(msg1, time(NULL), time(NULL));
	edit_msg(msg1);
	redraw_fld_line(outbox);

	return;
}

void cb_messages_dbl(FL_OBJECT * obj, long arg) {
	if(!current_message)
		return;

	if(current_folder == draft) {
		set_msg_date(current_message, time(NULL), time(NULL));
		edit_msg(current_message);
	} else if(current_folder == mftemplate)
		template_msg(current_message);
	else
		view_msg(current_message, 1);

	return;
}

void cb_messages(FL_OBJECT * obj, long arg) {
}

void cb_folders(FL_OBJECT * obj, long arg) {
	int num;
	struct _mail_folder *fld;

	num = fl_get_browser(obj);
	num--;

	if(!(fld = get_folder_by_index(num)))
		return;

	display_fld_status(fld);

	if(current_folder && (fl_mouse_button() == FL_RIGHT_MOUSE)) {
		chfld = fld;
		fl_dopup(fpup);
		chfld = NULL;
	}

	if(current_folder && (fl_mouse_button() == FL_MIDDLE_MOUSE))
		cb_folders_dbl(obj, arg);

	return;
}

void cb_folders_dbl(FL_OBJECT * obj, long arg) {
	unsigned long num;
	int flags, res, setlast = 0;
	struct _mail_folder *fld, *ofld;
	struct _mail_msg *msg = NULL;
	XEvent *xev;

	if(busy)
		return;
	busy = 1;
	xev = (XEvent *) fl_last_event();

	set_cursor(main_form, XC_watch);
	my_deactivate();
	num = current_folder->unread_num;
	current_folder->close(current_folder);
	if(num != current_folder->unread_num)
		update_title();

	current_message = NULL;
	num = fl_get_browser(obj) - 1;
	fld = get_folder_by_index(num);
	if(!fld) {
		set_current_message(NULL, 1);
		set_cursor(main_form, 0);
		my_activate();
		busy = 0;
		return;
	}

	num = fld->unread_num;
	flags = 0;
	if(xev->xbutton.state & ShiftMask)
		flags = FOPEN_UNREAD;

	if((res = fld->open(fld, flags)) == -1) {
		current_folder->open(current_folder, 0);
		set_current_message(current_folder->messages, 1);
		redraw_fld_line(current_folder);
		redraw_msg_win();
		my_activate();
		set_cursor(main_form, 0);
		fl_select_browser_line(obj, get_folder_index(current_folder) - 1);
		display_msg(MSG_WARN, "OPEN", "Can not open folder");
		busy = 0;
		return;
	}

	if((fld->sort != -1) && (fld->sort & MSG_ASCEND))
		setlast = 1;
	else if(sort_type & MSG_ASCEND)
		setlast = 1;

	if(fld != current_folder) {
		msg = fld->messages;
		while(msg) {
			if(setlast & (msg->next == NULL))
				break;
			if(msg->flags & UNREAD)
				break;
			msg = msg->next;
		}
	} else
		msg = get_msg_by_index(current_folder, current_index);

	ofld = current_folder;
	current_folder = fld;
	set_current_message(msg ? msg : current_folder->messages, 0);
	mark_to_us(current_folder);

	redraw_fld_line(ofld);
	if(res > 0)
		redraw_folders();
	else if(ofld == fld)
		restore_msg_win();
	else {
		redraw_fld_line(current_folder);
		redraw_msg_win();
	}

	refresh_folders();
	my_activate();
	set_cursor(main_form, 0);
	if(num != fld->unread_num)
		update_title();

	busy = 0;
	return;
}

void set_menu_imap() {
	int entries = 0;
	struct _imap_src *imap;
	list<struct _retrieve_src>::iterator p;

	fl_clear_menu(menu_imap);
	for(p = retrieve_srcs.begin(); p != retrieve_srcs.end(); p++) {
		if(p->type != RSRC_IMAP)
			continue;

		imap = (struct _imap_src *) p->spec;
		fl_addto_menu(menu_imap, p->name);
		entries++;
		fl_set_menu_item_mode(menu_imap, entries, imap_isconnected(imap) ?
							  FL_PUP_CHECK : FL_PUP_BOX);
	}

	return;
}

void cb_menu_imap(FL_OBJECT * obj, long arg) {
	int num;
	struct _imap_src *imap;
	list<struct _retrieve_src>::iterator p;

	if((num = fl_get_menu(obj)) <= 0)
		return;

	for(p = retrieve_srcs.begin(); p != retrieve_srcs.end(); p++) {
		if(p->type != RSRC_IMAP)
			continue;

		if(--num != 0)
			continue;

		imap = (struct _imap_src *) p->spec;
		if(imap_isconnected(imap)) {
			if((current_folder->type & F_IMAP) &&
			   (current_folder->spec == imap)) {
				set_current_folder(inbox);
				set_current_message(inbox->messages, 1);
			}

			my_deactivate();
			set_cursor(main_form, XC_watch);
			imap_close(imap, 1);
			redraw_folders();
			update_title();
			set_cursor(main_form, 0);
			my_activate();
			set_menu_imap();
		} else {
			my_deactivate();
			set_cursor(main_form, XC_watch);
			if(imap_init(imap) == 0) {
				set_menu_imap();
				redraw_folders();
			}
			set_menu_imap();
			update_title();
			set_cursor(main_form, 0);
			my_activate();
		}

		break;
	}

	return;
}

void cb_menu_misc(FL_OBJECT * obj, long arg) {
	int num;

	num = fl_get_menu(obj);
	switch(num) {
		case 1:
			addr_book_set_placement(-1, -1);
			addr_book(NULL, NULL, 0);
			break;

		case 2:
			fl_deactivate_form(main_form);
			xfm_config_new(1);
			fl_activate_form(main_form);
			break;

		case 3:
			fl_deactivate_form(main_form);
			xfm_config(1);
			fl_activate_form(main_form);
			break;

		case 4:
			fl_deactivate_form(main_form);
			set_el_size();
			fl_activate_form(main_form);
			break;

		case 5:
			sign_edit();
			break;

		case 6:
			fl_deactivate_form(main_form);
			rules_conf();
			fl_activate_form(main_form);
			break;

		case 7:
			get_new_mail(0, 0);
			break;

		case 8:
			log_win();
			break;

#ifdef  DEBUG
		case 9:     /* Debug */
			break;
#endif

		default:
			break;
	}
}

void cb_menu_help(FL_OBJECT * obj, long arg) {
	int num;
	struct _mail_msg *msg;
	struct _mime_msg *mime;
	char buf[255], bugtext[2048];

	num = fl_get_menu(obj);
	fl_deactivate_form(main_form);
	switch(num) {
		case 1:
			cb_help_button(NULL, 0);
			break;

		case 2:
			about(0);
			break;

		case 3:
			fl_show_message("BUG REPORT",
							"Please write down detailed information about the problem and press send",
							"(before this please consult with KNOWNBUGS file\nincluded in XFMail distribution)");

			msg = create_message(outbox);
			strcpy(buf, "XFMail bug report list <xfmail-bugs@xfmail.org>");
			msg->header->To = get_address(buf, ADDR_IGNORE_COMMAS);
			msg->header->Subject = strdup("XFMail bug report");
			snprintf(bugtext, sizeof(bugtext),
					 "XFMail %s%s on %s.\nCompiled %s\n\
XForms Version: %i Revision: %i\n\
------------------------Start of bug report------------------------------\n\
Detailed Information:\n\
\n\
\n\
How to reproduce: \n\
\n\
\n\
Operating System Version:  <PLEASE FILL ME IN>\n\
LIBC Version:  <OPTIONAL>\n\
------------------------End of bug report--------------------------------\n", \
VERSION, DEBUGVERSION, XF_OS, COMPILED, xforms_version, xforms_revision);

			update_message_text(msg, bugtext);

			snprintf(buf, sizeof(buf), "%s/.xfmrules", configdir);
			if(
			  (mime =
			   attach_file(msg, buf, &mailcap[DEFAULT_MAILCAP],
						   DEFAULT_ENCODING, ATT_NOUPDATE)) != NULL)
				set_mime_descr(mime, "Filtering rules file");

			snprintf(buf, sizeof(buf), "%s/.xfdefaults", configdir);
			if((mime = attach_file(msg, buf, &mailcap[DEFAULT_MAILCAP],
						   DEFAULT_ENCODING, ATT_NOUPDATE)) != NULL)
				set_mime_descr(mime, "XFdefaults file");

			snprintf(buf, sizeof(buf), "%s/.xfmfolders", configdir);
			if((mime = attach_file(msg, buf, &mailcap[DEFAULT_MAILCAP],
						   DEFAULT_ENCODING, ATT_NOUPDATE)) != NULL)
				set_mime_descr(mime, "Folders file");

			snprintf(buf, sizeof(buf), "%s/.xfmailrc", tmpdir);
			Config.save_file(buf,1);
			if((mime = attach_file(msg, buf, &mailcap[DEFAULT_MAILCAP],
						   DEFAULT_ENCODING, ATT_NOUPDATE)) != NULL)
				set_mime_descr(mime, "Configuration file");

			if(update_mime(msg) == -1)
				display_msg(MSG_WARN, "Bug report",
							"Failed to attach configuration files");

			unlink(buf);

			edit_msg(msg);
			set_edit_cursor(msg, 0, 5);
			refresh_folders();
			break;

		case 4:
			if(!display_msg
			   (MSG_QUEST, "Are you sure you want to subscribe?",
				"(mail will be sent to xfmail-users-request@xfmail.org)")) break;

			msg = create_message(outbox);
			sprintf(buf, "xfmail-users-request@xfmail.org");
			msg->header->To = get_address(buf, ADDR_IGNORE_COMMAS);
			update_message_text(msg, "subscribe xfmail-users\n");
			if((send_message(msg) == -1))
				display_msg(MSG_WARN, "subscribe",
							"Failed to send message to xfmail-users@xfmail.org");
			else
				fl_show_message("MAILING LIST", "Subscribe request sent to",
								"xfmail-users-request@xfmail.org");
			refresh_folders();
			break;

		case 5:
			if(!display_msg
			   (MSG_QUEST, "Are you sure you want to unsubscribe?",
				"(mail will be sent to xfmail-users-request@xfmail.org)"))
				break;

			msg = create_message(outbox);
			sprintf(buf, "xfmail-users@xfmail.org");
			msg->header->To = get_address(buf, ADDR_IGNORE_COMMAS);
			update_message_text(msg, "unsubscribe xfmail-users\n");
			if((send_message(msg) == -1))
				display_msg(MSG_WARN, "unsubscribe",
							"Failed to send message to xfmail-users-request@xfmail.org");
			else
				fl_show_message("MAILING LIST", "Unsubscribe request sent to",
								"xfmail-users-request@xfmail.org");
			refresh_folders();
			break;

		case 6:
			helpchapter(33);
			break;

		default:
			break;
	}
	fl_activate_form(main_form);
}

void cb_menu_file(FL_OBJECT * obj, long arg) {
	int num;
	const char *fname;
	FILE *afd;

	if(obj)
		num = fl_get_menu(obj);
	else
		num = arg;

	switch(num) {
		case 1:
			if(readonly) {
				display_msg(MSG_WARN, "XFMail",
							"Read-Only mode, can not save configuration");
				break;
			}

			Config.save(0);
			save_addressbooks();
			save_rules();
			save_folders_conf(NULL, F_MH | F_MBOX);
			save_imap_folders();
			save_sources(NULL);
			save_smtp_accounts(NULL);
			break;

		case 2:
			if(!current_message)
				break;
			fl_set_fselector_title("Choose file to append");
			if(!(fname = fl_show_file_selector("Save as", "", "", "message")))
				break;

			if(!(afd = fopen(fname, "a"))) {
				display_msg(MSG_WARN, "add", "Can not open %s", fname);
				break;
			}

			current_message->print(current_message, afd, 0);
			fclose(afd);
			break;

		case 3:
			clean_exit(0);
			break;

		default:

			break;
	}
}

void cb_button_save(FL_OBJECT * obj, long arg) {
	int header;
	FILE *ffd;
	const char *fname;

	if(!current_message)
		return;

	if(fl_get_button_numb(obj) == 3)
		header = 1;
	else
		header = 0;

	fl_set_fselector_title("Choose file to save as");
	if(!
	   (fname =
		fl_show_file_selector(header ? "Save message with header as" :
							  "Save message as", "", "", "message")))
		return;

	if((ffd = fopen(fname, "a+")) == NULL) {
		display_msg(MSG_WARN, "save", "Can not open %s", fname);
		return;
	}

	if(header)
		(*current_message->print) (current_message, ffd, 0);
	else
		(*current_message->print_body) (current_message, ffd);

	fclose(ffd);

	return;
}

void cb_button_abort(FL_OBJECT * obj, long arg) {
	abortbutton = 1;
}

int abortpressed() {
	my_check_forms2();
	if(abortbutton) {
		abortbutton = 0;
		return 1;
	}

	return 0;
}

int x11error_handle(Display * display, XErrorEvent * event) {
	char errbuf[255] = "";

	XGetErrorText(display, event->error_code, errbuf, sizeof(errbuf) - 1);
	if(!readonly) {
		if(!xfcompose) {
			save_imap_folders();
			save_folders_conf(NULL, F_MH | F_MBOX);
		}
		save_addressbooks();
		Config.save(0);
		save_sources(NULL);
		save_smtp_accounts(NULL);
	}

	close_procs();
	close_abook(NULL, NULL);
	cb_msg_autosave(NULL, 0);
	xfm_log_close_fd();

	display_msg(MSG_STDERR,
				*errbuf ? errbuf : "Non-fatal X11 error occured",
				"Report the bug with all the relevant information using the \"Bug report\" facility");

	return 0;
}

int x11ioerror_handle(Display * display) {
	if(!readonly) {
		if(!xfcompose) {
			save_imap_folders();
			save_folders_conf(NULL, F_MH | F_MBOX);
		}
		close_procs();
		save_addressbooks();
		Config.save(0);
		save_sources(NULL);
		save_smtp_accounts(NULL);
	}

	close_abook(NULL, NULL);
	cb_msg_autosave(NULL, 0);
	xfm_log_close_fd();

	display_msg(MSG_STDERR, "Fatal X11 error occured",
				"Configuration and unsaved messages has been saved, application terminated");
	exit(1);
	return 0;
}

void crash_handle(int s) {
	int res;

	display_msg(MSG_MSG,
				"The application crashed due to fatal error\nAll unfinished messages were saved",
				"Report the bug with all the relevant information\nusing the \"Bug report\" facility");

	fl_set_choices_shortcut("Yy#y", "Nn#n", "Cc#c");
	res = fl_show_choices("Shall I try to save your configuration files?\nYes = Try to save files (dangerous may cause corrupt config files(Not Suggested)\nNo = Hurry and abort so I can restart XFMail to fill out a bug report (Smart)\nCancel = Don\'t abort, don\'t save...I like to roll the dice! (dumb)  :)",
		 3, "Yes", "No", "Cancel", 1);

	switch(res) {
		case 1:  //Yes, old default behavior
			if(!readonly) {
				if(!xfcompose) {
					save_imap_folders();
					save_folders_conf(NULL, F_MH | F_MBOX);
				}
				close_procs();
				save_addressbooks();
				Config.save(0);
				save_sources(NULL);
				save_smtp_accounts(NULL);
			}

			close_abook(NULL, NULL);
			cb_msg_autosave(NULL, 0);
			xfm_log_close_fd();
		break;

		case 2:  //New behavior, smart people
			//Do nothing
		break;

		case 3:  //Dumb people
			return;
		break;

		default:
			//Dead End, shouldn't be here!
		;;
	}

   abort();
}

RETSIGTYPE clean_exit(int s) {
	char buf[255];

	if(!init)
		exit(0);

	if(!readonly) {
		save_addressbooks();
		if(s != SIGINT) {
			save_sources(NULL);
			save_smtp_accounts(NULL);
		} else  {
			fprintf(stderr, "SIGINT received: not saving sources and smtp_accounts\n");
		}

		if(!xfcompose) {
			save_imap_folders();
			save_folders_conf(NULL, F_MH | F_MBOX);
		}
	}

	msg_form_shutdown();

	if(Config.getInt("emptytrash", 0))
		if(s != SIGINT) {
			empty_trash_folders();
		} else {
			fprintf(stderr, "SIGINT received: not emptying trash\n");
		}

	if(main_form) {
		if(xofft > main_form->x)
			xofft = 0;
		if(yofft > main_form->y)
			yofft = 0;

        //Check for valid geometries
        if(((main_form->x - xofft) <= 0) || 
            ((main_form->y - yofft) <= 0) || 
            (main_form->w <= 0) ||
            (main_form->h <= 0)) {
			    fprintf(stderr, "Invalid Geomtry Not Saved\n");
            } else {
		        sprintf(buf, "%d %d %d %d", main_form->x - xofft,
				        main_form->y - yofft, main_form->w, main_form->h);
		        Config.setFlags("placement", CF_NOTCHANGED);
		        Config.set("placement", buf);
            }

		Config.setFlags("sfolder", CF_NOTCHANGED);
		Config.set("sfolder", get_folder_full_name(current_folder));
	}

	if(s != SIGINT)
		Config.save(1);
	else
		fprintf(stderr,"SIGINT received: not saving config\n");


	close_procs();

	close_abook(NULL, NULL);

	cleanup_rules();
	free_signatures();

	set_cursor(main_form, XC_watch);
	my_deactivate();

	close_all_folders();

	set_cursor(main_form, 0);
	imap_close_all(1);
	discard_all_folders();
	free_sources();

	if(main_form) {
		fl_freepup(mpup);
		fl_freepup(spup);
	choose_free();
	search_free();
	pop_account_free();
	xfm_log_free();
		fl_hide_form(main_form);
		fl_free_form(main_form);
	}

	xfm_log_close_fd();
	deinit_coders();
	exit(0);
}

void delete_messages() {
	int num, utitle, i;
	struct _mail_msg *msg, *cmsg = current_message;

	if(!current_folder || !current_folder->messages)
		return;

	if(busy)
		return;

	busy = 1;

	my_deactivate();
	set_cursor(main_form, XC_watch);
	utitle = 0;
	for(num = 1; num <= fl_get_browser_maxline(b_messages); num++) {
		if(fl_isselected_browser_line(b_messages, num)) {
			if((msg = get_msg_by_index(current_folder, num - 1))) {
				if(!(msg->status & LOCKED) && !(msg->status & MNOTEXISTS)) {
					if((msg->status & DELETED) || (msg->status & DELPERM)) {
						msg->status &= ~DELETED;
						msg->status &= ~DELPERM;
					} else
						msg->status |= DELETED;

					if(msg == cmsg) {
						current_message = NULL;
						cmsg = msg->next;
					}

					if(msg->flags & UNREAD)
						utitle = 1;
				}
			}
		}
	}
	current_folder->update(current_folder);
	redraw_fld_line(current_folder);
	for(i = 0; i < (int)mailbox.size(); i++) {
		if(mailbox[i]->status & FSKIP)
			continue;
		if(mailbox[i]->status & NOTRASH)
			redraw_fld_line(mailbox[i]);
	}

	set_current_message(cmsg ? cmsg :
						get_msg_by_index(current_folder, current_index),
						0);

	restore_msg_win();

	if(utitle)
		update_title();
	set_cursor(main_form, 0);
	my_activate();
	busy = 0;

	return;
}

struct _mail_msg *move_message_byrule(struct _mail_msg *msg) {
	struct _mail_folder *old_folder;
	int ind, i;

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

	i = (msg == current_message) ? 1 : 0;
	ind = get_msg_index(msg->folder, msg);

	old_folder = msg->folder;

	msg->status |= NOTINCOMING;
	if(apply_rule(msg, 0) == -1) {
		msg->status &= ~NOTINCOMING;
		return msg;
	}

	msg = get_msg_by_index(old_folder, ind);
	if(i)
		set_current_message(msg, 1);

	refresh_folders();

	return msg;
}

struct _mail_msg *move_message(struct _mail_msg *msg,
							   struct _mail_folder *fld) {
	struct _mail_folder *old_folder;
	int ind;

	if(!msg)
		return msg;

	if(!(msg->status & LOCKED) && !(msg->status & MNOTEXISTS)) {

		ind = get_msg_index(msg->folder, msg);
		old_folder = msg->folder;

		if(!fld)
			fld = choose_folder();

		if(!fld)
			return msg;

		if(fld == old_folder)
			return msg;

		if(msg == current_message)
			current_message = NULL;

		fld->move(msg, fld);
		if((fld->status & NOTRASH) || (old_folder->status & NOTRASH))
			update_title();

		msg = get_msg_by_index(old_folder, ind);
		while(msg &&
			  ((msg->status & MOVED) ||
			   (msg->status & DELETED) ||
			   (msg->status & DELPERM) || (msg->status & LOCKED)))
			msg = msg->next;

		if(old_folder == current_folder)
			set_current_message(msg, 1);

		redraw_fld_line(old_folder);
		redraw_fld_line(fld);
		if((current_folder == fld) || (current_folder == old_folder))
			restore_msg_win();
	}
	return msg;
}

void copy_messages(struct _mail_folder *fld) {
	int num;
	struct _mail_msg *msg;

	if(!current_folder)
		return;

	if(busy)
		return;

	busy = 1;

	set_cursor(main_form, XC_watch);
	my_deactivate();

	for(num = 1; num <= fl_get_browser_maxline(b_messages); num++) {
		if(fl_isselected_browser_line(b_messages, num)) {
			if((msg = get_msg_by_index(current_folder, num - 1))) {
				if(!fld) {
					fld = choose_folder();
					if(!fld) {
						my_activate();
						set_cursor(main_form, 0);
						busy = 0;
						return;
					}
				}
				msg->status |= COPIED;
				msg->folder = fld;
			}
		}
	}
	current_folder->update(current_folder);
	redraw_fld_line(current_folder);
	if(fld)
		redraw_fld_line(fld);
	my_activate();
	if(fld == current_folder)
		redraw_msg_win();
	update_title();
	set_cursor(main_form, 0);
	busy = 0;
}

void move_messages(struct _mail_folder *fld) {
	int num, utitle;
	struct _mail_msg *msg, *cmsg = current_message;

	if(!current_folder)
		return;

	if(fld && fld->status & FRONLY)
		return;

	if(busy)
		return;
	busy = 1;

	utitle = 0;
	set_cursor(main_form, XC_watch);
	my_deactivate();
	for(num = 1; num <= fl_get_browser_maxline(b_messages); num++) {
		if(fl_isselected_browser_line(b_messages, num)) {
			if((msg = get_msg_by_index(current_folder, num - 1))) {
				if((msg->status & LOCKED) ||
				   (msg->status & MNOTEXISTS) ||
				   (msg->folder->status & FRONLY)) continue;

				if(msg->flags & UNREAD)
					utitle = 1;

				if(!fld) {
					fld = choose_folder();
					fl_check_only_forms();
					if(!fld || (fld->status & FRONLY)) {
						my_activate();
						set_cursor(main_form, 0);
						busy = 0;
						return;
					}
				}

				if(cmsg == msg)
					cmsg = NULL;

				msg->status |= MOVED;
				msg->folder = fld;
			}
		}
	}
	current_folder->update(current_folder);
	redraw_fld_line(current_folder);
	if(fld)
		redraw_fld_line(fld);

	set_current_message(cmsg ? cmsg :
						get_msg_by_index(current_folder, current_index),
						0);

	restore_msg_win();

	if(utitle)
		update_title();
	my_activate();
	set_cursor(main_form, 0);
	busy = 0;
}

void update_title() {
	static int pres = -1;
	int res, i;
	char name[64];

	if(!main_form)
		return;

	res = 0;
	for(i = 0; i < (int)mailbox.size(); i++) {
		if(mailbox[i] &&
		   !(mailbox[i]->status & NOTRASH) &&
		   !(mailbox[i]->flags & FNCOUNT)) res += mailbox[i]->unread_num;
	}

	if(res == pres)
		return;

	if(res) {
		sprintf(name, "%d unread (XFMail)", res);
		if(pres > 0) {
			fl_set_form_title(main_form, name);
			XSetIconName(fl_display, main_form->window, name);
		} else
			set_main_icon(1, name);
	} else
		set_main_icon(0, "XFMail");

	pres = res;
	return;
}

void new_mail_notify() {
	struct _proc_info pinfo;
#ifdef  USE_SOUND
    string sPlay;
#endif

	switch(Config.getInt("beep", 1)) {
		case 1:
			fl_ringbell(100);
			break;

#ifdef  USE_SOUND
		case 2:
	case 4:
            if(Config.exist("play"))  {
			    sPlay = Config.get("play", "");
				if(play_sound(const_cast<char *>(sPlay.c_str()), 100) == -1)
					fl_ringbell(100);
			}
			break;

		case 3:
			init_pinfo(&pinfo);
            if(Config.exist("play")) {
			    sPlay = Config.get("play", "");
				if(exec_child(const_cast<char *>(sPlay.c_str()), &pinfo) == -1)
					fl_ringbell(100);
			}
			break;
#endif /* USE_SOUND */
	}
}

int get_new_mail(int local_only, int by_timer) {
	static int retrieving = 0;
	int i, k, res, spoolres, popres, imapres;
	long notify;
	list<struct _retrieve_src>::iterator p;
	unsigned long unum_old, unum_new;

	notify = 0;
	res = 0;
	spoolres = 0;
	popres = 0;
	imapres = 0;
	unum_old = unum_new = 0;

	if(busy || main_form->deactivated || retrieving) {
		fl_set_timer(inc_timer, Config.getInt("inctime", 180));
		return 0;
	}

	if((supress_errors == 1) && is_iconized())
		goto m_count;

	for(i = 0; i < (int)mailbox.size(); i++) {
		if(mailbox[i] &&
		   !(mailbox[i]->status & NOTRASH) &&
		   !(mailbox[i]->flags & FNCOUNT)) unum_old += mailbox[i]->unread_num;
	}

	my_deactivate();
	busy = 1;
	retrieving = 1;
	set_cursor(main_form, XC_watch);

	for(p = retrieve_srcs.begin(); p != retrieve_srcs.end(); p++) {
		if(p->retrieve == NULL)
			continue;

		if(local_only && (p->type != RSRC_SPOOL))
			continue;

		if(by_timer && (p->flags & RSRC_NOTIMER))
			continue;

		k = (p->retrieve) (&(*p), &notify);
		if(k < 0) {
			display_msg(MSG_WARN, "get_new_mail",
						"Failed to retrieve mail from %s",
						p->name);
			continue;
		}

		res += k;
		switch(p->type) {
			case RSRC_SPOOL:
				spoolres += k;
				break;

			case RSRC_POP:
				popres += k;
				break;

			case RSRC_IMAP:
				imapres += k;
				break;
		}
	}

	for(i = 0; i < (int)mailbox.size(); i++) {
		if((mailbox[i]->status & OPENED) || (mailbox[i]->flags & FCHECK)) {
			if(mailbox[i]->refresh(mailbox[i]) > 0) {
				redraw_fld(mailbox[i]);
				notify = 1;
			}
		}
	}

	for(i = 0; i < (int)mailbox.size(); i++) {
		if(mailbox[i] &&
		   !(mailbox[i]->status & NOTRASH) &&
		   !(mailbox[i]->flags & FNCOUNT)) unum_new += mailbox[i]->unread_num;
	}
	if(unum_new == unum_old)
		notify = 0;

	if(!res && notify) {
		new_mail_notify();
		my_activate();
		goto m_count;
	}

	if(current_folder)
		current_folder->update(current_folder);
	my_activate();
	if(res) {
		save_addressbooks();
		refresh_folders();
		redraw_fld_win();
		restore_msg_win();
		if(notify)
			new_mail_notify();
		if(res && notify && Config.getInt("incresults", 1))
			display_msg(MSG_MSG, "New mail received",
						"%d total\n(%d - spool %d - POP %d - IMAP)", res,
						spoolres, popres, imapres);
		else
			display_msg(MSG_LOG, "new mail",
						"%d total (%d - spool %d - POP %d - IMAP)", res,
						spoolres, popres, imapres);
	} else
		refresh_folders();

	m_count:
	update_title();
	refresh_folders();

	fl_set_timer(inc_timer, Config.getInt("inctime", 180));
	set_cursor(main_form, 0);
	busy = 0;
	retrieving = 0;

	/* return number of new, unread messages (those that are counted) */
	return (unum_new - unum_old);
}

void cb_menu_messages(FL_OBJECT * obj, long arg) {
	int num, i;
	struct _mail_msg *msg;
	struct _pop_src *popsrc;

	if(arg == 0)
		num = fl_get_menu(obj);
	else
		num = arg;

	switch(num) {
		case 1:     /* View */
			view_msg(current_message, 1);
			break;

		case 2:     /* Edit */
			edit_msg(current_message);
			redraw_fld_line(current_folder);
			redraw_msg(current_message);
			break;

		case 3:     /* Delete */
			delete_messages();
			break;

		case 4:     /* Move */
			move_messages(NULL);
			break;

		case 5:     /* Copy */
			copy_messages(NULL);
			break;

		case 6:     /* Mark */
			for(num = 1; num <= fl_get_browser_maxline(b_messages); num++) {
				if(fl_isselected_browser_line(b_messages, num)) {
					if((msg = get_msg_by_index(current_folder, num - 1))) {
						if(!(msg->status & LOCKED))
							msg->flags |= MARKED;
					}
				}
			}

			current_folder->update(current_folder);
			restore_msg_win();
			break;

		case 7:     /* Unmark */
			for(num = 1; num <= fl_get_browser_maxline(b_messages); num++) {
				if(fl_isselected_browser_line(b_messages, num)) {
					if((msg = get_msg_by_index(current_folder, num - 1))) {
						if(!(msg->status & LOCKED)) {
							msg->flags &= ~MARKED;
							msg->status &= ~MARKTMP;
						}
					}
				}
			}

			current_folder->update(current_folder);
			restore_msg_win();
			break;

		case 8:     /* Mark Read/Unread */
			for(num = 1; num <= fl_get_browser_maxline(b_messages); num++) {
				if(fl_isselected_browser_line(b_messages, num)) {
					if((msg = get_msg_by_index(current_folder, num - 1))
					   && !(msg->status & LOCKED)) {
						if(msg->flags & UNREAD) {
							msg->flags &= ~UNREAD;
							if(msg->folder->unread_num)
								msg->folder->unread_num--;
						} else {
							msg->flags |= UNREAD;
							msg->folder->unread_num++;
						}
					}
				}
			}

			current_folder->update(current_folder);
			restore_msg_win();
			redraw_fld_line(current_folder);
			update_title();
			break;

		case 9:     /* Print */
			set_cursor(main_form, XC_watch);
			my_deactivate();
			lpr_message(current_message);
			my_activate();
			set_cursor(main_form, 0);
			break;

		case 10:        /* Apply rules */
			set_cursor(main_form, XC_watch);
			my_deactivate();
			for(num = 1; num <= fl_get_browser_maxline(b_messages); num++) {
				if(fl_isselected_browser_line(b_messages, num)) {
					if((msg = get_msg_by_index(current_folder, num - 1))) {
						if(!(msg->status & LOCKED) &&
						   !(msg->status & MNOTEXISTS)) apply_rule(msg, 1);
					}
				}
			}

			current_folder->update(current_folder);
			my_activate();
			refresh_folders();
			set_cursor(main_form, 0);
			break;

		case 11:        /* Select all */
			fl_freeze_form(main_form);
			for(num = 1; num <= fl_get_browser_maxline(b_messages); num++)
				fl_select_browser_line(b_messages, num);
			fl_unfreeze_form(main_form);
			break;

		case 12:        /* Select marked */
			fl_freeze_form(main_form);
			for(num = 1; num <= fl_get_browser_maxline(b_messages); num++)
				if((msg = get_msg_by_index(current_folder, num - 1)) &&
				   ((msg->flags & MARKED) || (msg->status & MARKTMP)))
					fl_select_browser_line(b_messages, num);
				else
					fl_deselect_browser_line(b_messages, num);
			fl_unfreeze_form(main_form);
			break;

		case 13:        /* Delete from POP server */
			if(current_message == NULL)
				break;
			set_cursor(main_form, XC_watch);
			my_deactivate();
			i = 0;
			popsrc = NULL;
			for(num = 1; num <= fl_get_browser_maxline(b_messages); num++) {
				if(abortpressed())
					break;

				if(fl_isselected_browser_line(b_messages, num)) {
					if((msg = get_msg_by_index(current_folder, num - 1))) {
						fl_check_only_forms();
						if(popsrc == NULL) {
							if((popsrc = get_msg_popsrc(msg)) != NULL)
								pop_init(popsrc);
						}
						if(pop_delmsg_by_uidl(get_msg_popsrc(msg), msg)
						   != -1) {
							i++;
							redraw_msg(msg);
						}
					}
				}
			}

			if(i)
				display_msg(MSG_MSG, "POP",
							"Deleted %d messages from POP server", i);
			else
				display_msg(MSG_WARN, "POP", "No messages were deleted");

			my_activate();
			set_cursor(main_form, 0);
			if(popsrc)
				pop_end(popsrc);
			break;

		case 14:        /* Refresh */
			set_cursor(main_form, XC_watch);
			my_deactivate();
			for(num = 1; num <= fl_get_browser_maxline(b_messages); num++) {
				if(fl_isselected_browser_line(b_messages, num)) {
					if((msg = get_msg_by_index(current_folder, num - 1))) {
						if(msg->status & LOCKED)
							continue;
						msg->refresh(msg);
						if(msg == current_message)
							msg_preview(msg);
						redraw_msg(msg);
					}
				}
			}

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

		case 15:        /* Options */
			if(current_message == NULL)
				break;
			set_cursor(main_form, XC_watch);
			my_deactivate();
			message_conf(current_message);
			my_activate();
			set_cursor(main_form, 0);
			break;

		case 16:        /* Pipe */
			if(current_message == NULL)
				break;
			pipe_msg(current_message, (char *) fl_show_input("Pipe to:", ""));
			break;

		case 17:        /* Download */
			if((current_message == NULL) ||
			   !(current_message->flags & H_ONLY)) break;
			set_cursor(main_form, XC_watch);
			my_deactivate();
			if(current_message->type & M_IMAP)
				current_message->get_file(current_message);
			else if((popsrc = get_msg_popsrc(current_message)) != NULL)
				pop_getfull_msg(popsrc, current_message);
			my_activate();
			set_cursor(main_form, 0);
			redraw_msg(current_message);
			msg_preview(current_message);
			break;
	}
}

int is_iconized() {
	XWindowAttributes xattr;

	if(!main_form)
		return 1;

	if(Config.getInt("incwhenicon", 1)) {
		xattr.map_state = IsUnmapped;
		if(XGetWindowAttributes(fl_display, main_form->window, &xattr)) {
			if(xattr.map_state != IsUnmapped)
				return 1;
		}
	}

	return 0;
}

void send_all() {
	struct _mail_msg *msg;
	int offl, opened;

	fl_set_timer(send_timer, Config.getInt("sendtime", 0));
	if(busy || main_form->deactivated)
		return;

	if(supress_errors && is_iconized())
		return;

	busy = 1;
	offl = offline;
	offline = 0;
	opened = 0;

	if(!(outbox->status & OPENED)) {
		if(outbox->open(outbox, 0) == -1) {
			display_msg(MSG_WARN, "send all", "Can not open %s", OUTBOX);
			offline = offl;
			busy = 0;
			return;
		} else
			opened = 1;
	}

	set_cursor(main_form, XC_watch);
	my_deactivate();

	msg = outbox->messages;
	while(msg) {
		msg->flags |= NOT_SENT;
		msg = msg->next;
	}

	outbox->update(outbox);

	if(opened)
		outbox->close(outbox);

	my_activate();
	set_cursor(main_form, 0);

	offline = offl;
	refresh_folders();

	busy = 0;
	return;
}

void cb_menu_send(FL_OBJECT * obj, long arg) {
	struct _mail_msg *msg;
	int num;
	char *sel;

	if(arg == 0)
		num = fl_get_menu(obj);
	else
		num = arg;

	my_deactivate();
	switch(num) {
		case 1:
			set_cursor(main_form, XC_watch);
			msg = create_message(outbox);
			edit_msg(msg);
			refresh_folders();
			set_cursor(main_form, 0);
			break;

		case 2:
			set_cursor(main_form, XC_watch);
			sel = msgpane ? fl_get_textedit_seltext(msgpane) : NULL;
			edit_msg(get_reply_msg(current_message, sel, 0));
			if(sel)
				free(sel);
			refresh_folders();
			redraw_msg(current_message);
			set_cursor(main_form, 0);
			break;

		case 3:
			set_cursor(main_form, XC_watch);
			sel = msgpane ? fl_get_textedit_seltext(msgpane) : NULL;
			edit_msg(get_reply_msg(current_message, sel, 2));
			if(sel)
				free(sel);
			refresh_folders();
			redraw_msg(current_message);
			set_cursor(main_form, 0);
			break;

		case 4:
			set_cursor(main_form, XC_watch);
			sel = msgpane ? fl_get_textedit_seltext(msgpane) : NULL;
			edit_msg(get_fwd_msg(current_message, sel));
			if(sel)
				free(sel);
			refresh_folders();
			redraw_msg(current_message);
			set_cursor(main_form, 0);
			break;

		case 5:     /* Bounce (resend) */
			if(!current_message)
				break;

			current_message->status |= LOCKED;
			if(!(msg = outbox->copy(current_message, outbox))) {
				display_msg(MSG_WARN, "bounce", "Can not copy message");
				current_message->status &= ~LOCKED;
				break;
			}
			current_message->status &= ~LOCKED;
			msg->status &= ~LOCKED;
			msg->status |= MSGNEW;

			msg->get_header(msg);
			add_field(msg, BOUNCE_ORGMSG, get_msg_url(current_message));
			discard_address(msg->header->To);
			discard_address(msg->header->Cc);
			discard_address(msg->header->Bcc);
			msg->header->To = NULL;
			msg->header->Cc = NULL;
			msg->header->Bcc = NULL;
			msg->status |= CHANGED;
			msg->update(msg);

			edit_msg(msg);
			redraw_fld_line(outbox);
			refresh_folders();
			break;

		case 6:
			send_all();
			break;

		default:
			break;
	}
	my_activate();
}

void cb_menu_folders(FL_OBJECT * obj, long arg) {
	int num, res, i, opened;
	char *str, *p;
	struct _mail_folder *fld, *ofld;
	struct _mail_msg *msg;
	char oldname[MAX_FOLD_NAME_LEN];

	if(busy)
		return;

	busy = 1;

	if(arg == 0)
		num = fl_get_menu(obj);
	else
		num = arg;

	switch(num) {
		case 1:
			set_cursor(main_form, XC_watch);
			my_deactivate();
			fld = create_folder(NULL, 0);
			redraw_fld_win();
			my_activate();
			set_cursor(main_form, 0);
			break;
		case 2:
			set_cursor(main_form, XC_watch);
			my_deactivate();
			create_subfolder(chfld ? chfld : current_folder, NULL);
			redraw_fld_win();
			my_activate();
			set_cursor(main_form, 0);
			break;
		case 3:
			fld = chfld ? chfld : current_folder;

			res =
			display_msg(MSG_QUEST | MSG_DEFNO, "WARNING",
						"Folder %s with all messages will be deleted",
						current_folder->name(fld));
			if(res) {
				set_cursor(main_form, XC_watch);
				my_deactivate();
				if(fld == current_folder) {
					if(fld->fdelete(fld) == 0) {
						current_folder = NULL;
						set_current_folder(inbox);
					}
				} else
					fld->fdelete(fld);
				my_activate();
				set_cursor(main_form, 0);
				redraw_folders();
			}
			save_folders_conf(NULL, F_MH | F_MBOX);
			break;
		case 4:
			fld = chfld ? chfld : current_folder;
			str = (char *) fl_show_input("Enter new name:", fld->sname);

			if(!str || !*str) {
				busy = 0;
				break;
			}

			fl_deactivate_all_forms();
			p = str;
			while(*p != '\0') {
				if(!isgraph(*p)) {
					display_msg(MSG_WARN, "rename",
								"Illegal character in folder name");
					fl_activate_all_forms();
					busy = 0;
					break;
				}
				p++;
			}

			strcpy(oldname, get_folder_full_name(fld));
			if(fld->rename(fld, str) == -1) {
				display_msg(MSG_WARN, "rename",
							"Can not rename folder %s to %s", fld->sname, str);
				fl_activate_all_forms();
				break;
			}

			rule_rename_folder(fld, oldname);
			redraw_fld_win();
			fl_activate_all_forms();
			save_folders_conf(NULL, F_MH | F_MBOX);
			break;

		case 5:
			set_cursor(main_form, XC_watch);
			my_deactivate();

			fld = chfld ? chfld : choose_folder();

			if(!fld) {
				my_activate();
				set_cursor(main_form, 0);
				break;
			}

			current_folder->close(current_folder);
			ofld = current_folder;

			if((res = fld->open(fld, 0)) == -1) {
				display_msg(MSG_WARN, "OPEN", "Can not open folder");
				my_activate();
				set_cursor(main_form, 0);
				break;
			}

			current_folder = fld;
			mark_to_us(current_folder);
			redraw_fld_line(current_folder);
			redraw_fld_line(ofld);
			set_current_message(current_folder->messages, 0);
			if(res > 0)
				redraw_folders();
			else
				redraw_msg_win();

			my_activate();
			set_cursor(main_form, 0);

			break;

		case 6:
			set_cursor(main_form, XC_watch);
			my_deactivate();

			fld = chfld ? chfld : choose_folder();

			if(!fld) {
				my_activate();
				set_cursor(main_form, 0);
				break;
			}

			current_folder->close(current_folder);
			ofld = current_folder;

			if((res = fld->open(fld, FOPEN_UNREAD)) == -1) {
				display_msg(MSG_WARN, "OPEN", "Can not open folder");
				my_activate();
				set_cursor(main_form, 0);
				break;
			}

			current_folder = fld;
			mark_to_us(current_folder);
			redraw_fld_line(current_folder);
			redraw_fld_line(ofld);
			set_current_message(current_folder->messages, 0);
			if(res > 0)
				redraw_folders();
			else
				redraw_msg_win();

			my_activate();
			set_cursor(main_form, 0);

			break;

		case 7:
			set_cursor(main_form, XC_watch);
			my_deactivate();
			empty_trash_folders();
			my_activate();
			set_cursor(main_form, 0);
			display_fld_status(current_folder);
			break;

		case 8:
			set_cursor(main_form, XC_watch);
			my_deactivate();
			fld = chfld ? chfld : current_folder;
			opened = 0;
			if(!(fld->status & OPENED)) {
				fld->open(fld, FOPEN_UNREAD);
				opened = 1;
			}

			msg = fld->messages;
			while(msg) {
				if(msg->flags & UNREAD) {
					msg->flags &= ~UNREAD;
					if(fld->unread_num)
						fld->unread_num--;
					msg->update(msg);
				}
				msg = msg->next;
			}

			redraw_fld(fld);
			if(opened)
				fld->close(fld);
			set_cursor(main_form, 0);
			my_activate();
			update_title();
			break;

		case 9:
			search_msgs();
			break;

		case 10:
			set_cursor(main_form, XC_watch);
			my_deactivate();
			for(i = 0; i < (int)mailbox.size(); i++) {
				if(abortpressed())
					break;

				if((mailbox[i] != NULL) && (mailbox[i] != current_folder)) {
					display_msg(MSG_STAT, NULL, "Rescanning %s",
								mailbox[i]->name(mailbox[i]));
					if(mailbox[i]->rescan(mailbox[i]) == -1)
						break;
				}
			}
			redraw_folders();
			update_title();
			my_activate();
			set_cursor(main_form, 0);
			break;

		case 11:
			fl_deactivate_all_forms();
			folder_conf(chfld ? chfld : current_folder);
			fl_activate_all_forms();
			break;

		case 12:
			expand_collapse_tree(chfld ? chfld : current_folder, 1);
			restore_fld_win();
			break;

		case 13:
			fld = chfld ? chfld : current_folder;
			if(!fld || !display_msg(MSG_QUEST, "EXPUNGE", "Are you sure?"))
				break;
			set_cursor(main_form, XC_watch);
			my_deactivate();
			fld->expunge(fld);
			my_activate();
			set_cursor(main_form, 0);
			remove_nonexistent(fld);
			if(fld == current_folder)
				set_current_message(current_folder->messages, 0);
			redraw_fld(fld);
			refresh_folders();
			update_title();
			break;

		default:
			break;
	}

	busy = 0;
}

void cb_button_edit(FL_OBJECT * obj, long arg) {
	edit_msg(current_message);
	refresh_folders();
}

void cb_button_exit(FL_OBJECT * obj, long arg) {
	if(Config.getInt("cexit", 0)
	   && !display_msg(MSG_QUEST, "EXIT", "Are you sure?"))
		return;

	clean_exit(0);
}

void cb_button_newmail(FL_OBJECT * obj, long arg) {
	struct _mail_msg *msg;

	msg = create_message(outbox);
	edit_msg(msg);
	refresh_folders();
}

void cb_button_print(FL_OBJECT * obj, long arg) {
	set_cursor(main_form, XC_watch);
	lpr_message(current_message);
	set_cursor(main_form, 0);
}

void cb_button_view(FL_OBJECT * obj, long arg) {
	view_msg(current_message, 1);
}

void cb_button_reply(FL_OBJECT * obj, long arg) {
	char *sel;

	set_cursor(main_form, XC_watch);
	my_deactivate();
	sel = msgpane ? fl_get_textedit_seltext(msgpane) : NULL;
	if(fl_get_button_numb(obj) == 3)
		edit_msg(get_reply_msg(current_message, sel, 0));
	else
		edit_msg(get_reply_msg(current_message, sel, 1));
	if(sel)
		free(sel);
	refresh_folders();
	redraw_msg(current_message);
	my_activate();
	set_cursor(main_form, 0);
}

void cb_button_forward(FL_OBJECT * obj, long arg) {
	char *sel;

	set_cursor(main_form, XC_watch);
	my_deactivate();
	sel = msgpane ? fl_get_textedit_seltext(msgpane) : NULL;
	edit_msg(get_fwd_msg(current_message, sel));
	if(sel)
		free(sel);
	redraw_msg(current_message);
	refresh_folders();
	my_activate();
	set_cursor(main_form, 0);
}

void cb_button_move(FL_OBJECT * obj, long arg) {
	struct _mail_folder *fld;

	if(fl_get_button_numb(obj) == 3) {
		if((fld = pup_choose_folder(main_form)) == NULL)
			return;
	} else
		fld = NULL;

	move_messages(fld);
}

void cb_button_retr(FL_OBJECT * obj, long arg) {
	if(fl_get_button_numb(obj) == 3)
		get_new_mail(1, 0);
	else
		get_new_mail(0, 0);
}

void cb_button_delete(FL_OBJECT * obj, long arg) {
	if(fl_get_button_numb(obj) != 3)
		delete_messages();
	else {
		if(!current_folder ||
		   !display_msg(MSG_QUEST, "EXPUNGE", "Are you sure?"))
			return;
		set_cursor(main_form, XC_watch);
		my_deactivate();
		current_folder->expunge(current_folder);
		remove_nonexistent(current_folder);
		set_current_message(current_folder->messages, 0);
		redraw_fld(current_folder);
		refresh_folders();
		update_title();
		set_cursor(main_form, 0);
		my_activate();
	}
}

void cb_button_send(FL_OBJECT * obj, long arg) {
	int num, offl;
	struct _mail_msg *msg;
	int answer;

	if(!current_folder)
		return;

	if(busy)
		return;

	answer = 0;

	offl = offline;
	if(current_folder == outbox)
		offline = 0;

	set_cursor(main_form, XC_watch);
	for(num = 1; num <= fl_get_browser_maxline(b_messages); num++) {
		if(fl_isselected_browser_line(b_messages, num)) {

			if(!answer
			   && !display_msg(MSG_QUEST, "Send",
							   "Are you sure you want to send selected message(s)?")) {
				set_cursor(main_form, 0);
				offline = offl;
				return;
			}

			answer = 1;

			if((msg = get_msg_by_index(current_folder, num - 1)))
				msg->flags |= NOT_SENT;
			else
				continue;

			if((msg->status & LOCKED) || (msg->status & MNOTEXISTS))
				continue;

		}
	}

	current_folder->update(current_folder);
	set_current_message(current_folder->messages, 1);
	offline = offl;
	refresh_folders();
	set_cursor(main_form, 0);
	return;
}

void cb_timer(FL_OBJECT * obj, long arg) {
	if(supress_errors)
		return;
	supress_errors = 1;
	get_new_mail(0, 1);
	supress_errors = 0;
}

void cb_send_timer(FL_OBJECT * obj, long arg) {
	if(supress_errors)
		return;
	supress_errors = 1;
	send_all();
	supress_errors = 0;
}

void expire_folders() {
	int i, opened;

	for(i = 0; i < (int)mailbox.size(); i++) {
		if(mailbox[i]->expire <= 0)
			continue;
		opened = 0;
		if(!(mailbox[i]->status & OPENED) ||
		   (mailbox[i]->status & FUNREAD)) {
			if(mailbox[i]->open(mailbox[i], 0) != 0)
				continue;
			opened = 1;
		}
		expire_msgs(mailbox[i]);
		if(opened && (mailbox[i] != current_folder))
			mailbox[i]->close(mailbox[i]);

		redraw_fld_line(mailbox[i]);
		if(current_folder == mailbox[i]) {
			current_index = 0;
			current_message = NULL;
			redraw_msg_win();
		}
	}
}

void empty_trash_folders() {
	int i;

	for(i = 0; i < (int)mailbox.size(); i++) {
		if(mailbox[i]->status & NOTRASH) {
			mailbox[i]->empty(mailbox[i]);
			if(mailbox[i]->num_msg)
				display_msg(MSG_WARN, "Empty Trash", "Can not empty %s",
							mailbox[i]->name(mailbox[i]));
			redraw_fld_line(mailbox[i]);
			if(current_folder == mailbox[i]) {
				set_current_message(NULL, 0);
				redraw_msg_win();
			}
		}
	}
}

void cb_preview_timer(FL_OBJECT * obj, long arg) {
	if(!current_message || !(current_message->flags & UNREAD))
		return;

	current_message->flags &= ~UNREAD;
	current_message->update(current_message);
	redraw_msg(current_message);
	if(current_message->folder->unread_num)
		current_message->folder->unread_num--;
	update_title();
	redraw_fld_line(current_message->folder);

	return;
}

void cb_imap_timer(FL_OBJECT * obj, long arg) {
	if(busy || main_form->deactivated || supress_errors) {
		fl_set_timer(imap_timer,
					 Config.getInt("imaptime", 600)); 
		return;
	}

	busy = 1;
	my_deactivate();
	imap_timer_cb();
	my_activate();
	if(current_folder && (current_folder->type == F_IMAP) &&
	   (current_folder->status & FRESCAN)) {
		current_message = current_folder->messages;
		current_index = 0;
		redraw_fld(current_folder);
	}
	busy = 0;
}

void cb_trash_timer(FL_OBJECT * obj, long arg) {
	fl_set_timer(obj, Config.getInt("trashtime", 0) * 60);
	if(busy || main_form->deactivated)
		return;

	if(is_iconized())
		return;

	if(supress_errors)
		return;

	supress_errors = 1;
	busy = 1;
	my_deactivate();
	empty_trash_folders();
	expire_folders();
	my_activate();
	busy = 0;
	supress_errors = 0;
	fl_set_timer(obj, Config.getInt("trashtime", 0) * 60);
}

void cb_msgpane(FL_OBJECT * obj, long num) {
	if(current_message)
		msg_preview(current_message);
}

void select_found() {
	struct _mail_msg *msg;

	fl_freeze_form(main_form);
	fl_deselect_browser(b_messages);
	msg = current_folder->messages;
	while(msg) {
		if(msg->status & MARKTMP)
			fl_select_browser_line(b_messages,
								   get_msg_index(current_folder, msg) + 1);
		msg = msg->next;
	}
	fl_unfreeze_form(main_form);
}

FL_FORM *create_main_form(void) {
	FL_OBJECT *obj;
	FL_FORM *f_mail;
	int menubox_bottom = 3;
	int menus_y_offset = menubox_bottom;
	int buttons_y_bottom = menubox_bottom + 25;
	int browserbottoms = 64;
	int browserheights = 518;
	int msgpanefix = msgpanesize ? msgpanesize + 2 : 0;

	f_mail = fl_bgn_form(FL_NO_BOX, 778, 615 + msgpanefix);
	obj = fl_add_box(FL_FLAT_BOX, 0, 0, 778, 615 + msgpanefix, "");
	
	/* Message pane preview placed _under_ message browser fix */ 
	obj =
	fl_add_browser(FL_HOLD_BROWSER, 3, browserbottoms, fbrowsersize,
				   browserheights + msgpanesize + 3, "");
	fl_set_object_resize(obj, FL_RESIZE_Y);
	fl_set_object_gravity(obj, NorthWestGravity, SouthGravity);
	fl_set_browser_fontsize(obj,
							Config.getInt("FoldersFSize",
										  FL_NORMAL_SIZE));
	fl_set_browser_fontstyle(obj,
							 Config.getInt("FoldersFStyle",
										   FL_FIXEDBOLD_STYLE));
	fl_set_object_lsize(obj,
						Config.getInt("FoldersFSize",
									  FL_NORMAL_SIZE));
	fl_set_object_lstyle(obj,
						 Config.getInt("FoldersFStyle",
									   FL_FIXEDBOLD_STYLE));
	fl_set_object_color(obj,
						Config.getInt("FoldersBgCol",
									  FL_TOP_BCOL),
						Config.getInt("FoldersFgCol",
									  FL_YELLOW));
	fl_set_object_callback(obj, cb_folders, 0);
	fl_set_browser_dblclick_callback(obj, cb_folders_dbl, 0);
	obj->input = TRUE;
	b_folders = obj;

	obj =
	fl_add_browser(FL_MULTI_BROWSER, 5 + fbrowsersize, browserbottoms,
				   770 - fbrowsersize, browserheights, "");
	fl_set_object_resize(obj, FL_RESIZE_ALL);
	fl_set_object_gravity(obj, NorthWestGravity, SouthEastGravity);
	fl_set_browser_fontsize(obj,
							Config.getInt("MessagesFSize",
										  FL_NORMAL_SIZE));
	fl_set_browser_fontstyle(obj,
							 Config.getInt("MessagesFStyle",
										   FL_FIXED_STYLE));
	fl_set_object_color(obj,
						Config.getInt("MessagesBgCol",
									  FL_TOP_BCOL),
						Config.getInt("MessagesFgCol",
									  FL_YELLOW));
	fl_set_object_callback(obj, cb_messages, 0);
	fl_set_browser_dblclick_callback(obj, cb_messages_dbl, 0);
	obj->input = TRUE;
	b_messages = obj;

	obj =
	fl_add_button(FL_HIDDEN_BUTTON, 3 + fbrowsersize, browserbottoms,
				  2, browserheights + msgpanesize + 3, "");
	fl_set_object_resize(obj, FL_RESIZE_Y);
	fl_set_object_gravity(obj, NorthWestGravity, SouthGravity);
	fl_set_object_callback(obj, cb_fbutton, 0);
	fl_set_object_posthandler(obj, cb_fbutton_handler);
	f_button = obj;

	status = obj =
			 fl_add_text(FL_NORMAL_TEXT, 3,
						 browserbottoms + browserheights + msgpanefix + 3, 772,
						 27, "");
	fl_set_object_lsize(obj, FL_SMALL_SIZE);
	fl_set_object_resize(obj, FL_RESIZE_X);
	fl_set_object_gravity(obj, SouthWestGravity, SouthEastGravity);
	fl_set_object_boxtype(obj, FL_DOWN_BOX);
	fl_set_object_color(obj, FL_MCOL, FL_BLUE);
	fl_set_object_lcol(obj, FL_BLUE);

	if(msgpanesize) {
		msgpane = obj =
				  fl_add_textedit(FL_NORMAL_TEXTEDIT, 5 + fbrowsersize,
								  browserbottoms + browserheights + 2, 770 - fbrowsersize,
								  msgpanesize, "");
		fl_set_object_resize(obj, FL_RESIZE_ALL);
		fl_set_object_gravity(obj, SouthWestGravity, 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); fl_textedit_readonly(obj, 1);
		fl_set_object_callback(obj, cb_msgpane, 0);
		fl_textedit_set_callback(obj, text_dbl_call,
								 FL_TEXTEDIT_DBL_CALLBACK);

		obj =
		fl_add_button(FL_HIDDEN_BUTTON, 5 + fbrowsersize,
					  browserbottoms + browserheights, 770 - fbrowsersize, 2, "");
		fl_set_object_resize(obj, FL_RESIZE_X);
		fl_set_object_gravity(obj, SouthWestGravity, SouthEastGravity);
		fl_set_object_callback(obj, cb_mbutton, 0);
		fl_set_object_posthandler(obj, cb_mbutton_handler);
		m_button = obj;
	}

	obj = fl_add_frame(FL_UP_FRAME, 3, menubox_bottom, 772, 20, "");
	fl_set_object_resize(obj, FL_RESIZE_X);
	fl_set_object_gravity(obj, NorthWestGravity, 0);

	obj =
	fl_add_menu(FL_PULLDOWN_MENU, 10, menus_y_offset, 30, 20, "File");
	menu_file = obj;
	fl_set_object_boxtype(obj, FL_FLAT_BOX);
	fl_set_object_lalign(obj, FL_ALIGN_LEFT);
	fl_set_menu(obj, "Save options|Save to File (Alt+S)|Exit (Alt+X)");
	fl_set_object_callback(obj, cb_menu_file, 0);
	fl_set_object_shortcut(obj, "#L", 1);

	fl_set_menu_item_shortcut(obj, 1, "Oo#o");
	fl_set_menu_item_shortcut(obj, 2, "Ss#s");
	fl_set_menu_item_shortcut(obj, 2, "Xx#x");

	fl_set_object_resize(obj, FL_RESIZE_NONE);
	fl_set_object_gravity(obj, NorthWestGravity, 0);

	obj =
	fl_add_menu(FL_PULLDOWN_MENU, 50, menus_y_offset, 70, 20,
				"Message");
	menu_message = obj;
	fl_set_object_boxtype(obj, FL_FLAT_BOX);
	fl_set_menu(obj, MESG_MENU);
	fl_set_object_callback(obj, cb_menu_messages, 0);
	fl_set_object_shortcut(obj, "#G", 1);

	fl_set_menu_item_shortcut(obj, 1, "Vv#v");
	fl_set_menu_item_shortcut(obj, 2, "Ee#e");
	fl_set_menu_item_shortcut(obj, 3, "Dd#d");
	fl_set_menu_item_shortcut(obj, 4, "Mm#m");
	fl_set_menu_item_shortcut(obj, 5, "Cc#c");
	fl_set_menu_item_shortcut(obj, 6, "Rr#r");
	fl_set_menu_item_shortcut(obj, 7, "Uu#u");
	fl_set_menu_item_shortcut(obj, 8, "Kk#k");
	fl_set_menu_item_shortcut(obj, 9, "Pp#p");
	fl_set_menu_item_shortcut(obj, 10, "Aa#a");
	fl_set_menu_item_shortcut(obj, 11, "Ss#s");
	fl_set_menu_item_shortcut(obj, 12, "Ll#l");
	fl_set_menu_item_shortcut(obj, 13, "Tt#t");
	fl_set_menu_item_shortcut(obj, 14, "Rr#r");
	fl_set_menu_item_shortcut(obj, 15, "Oo#o");
	fl_set_menu_item_shortcut(obj, 16, "Ii#i");
	fl_set_menu_item_shortcut(obj, 17, "Ww#i");

	fl_set_object_resize(obj, FL_RESIZE_NONE);
	fl_set_object_gravity(obj, NorthWestGravity, 0);

	obj =
	fl_add_menu(FL_PULLDOWN_MENU, 120, menus_y_offset, 70, 20,
				"Folder");
	menu_folders = obj;
	fl_set_object_boxtype(obj, FL_FLAT_BOX);
	fl_set_menu(obj, FOLD_MENU);
	fl_set_object_callback(obj, cb_menu_folders, 0);
	fl_set_object_shortcut(obj, "#O", 1);

	fl_set_menu_item_shortcut(obj, 1, "Cc#c");
	fl_set_menu_item_shortcut(obj, 2, "Ff#f");
	fl_set_menu_item_shortcut(obj, 3, "Dd#d");
	fl_set_menu_item_shortcut(obj, 4, "Rr#r");
	fl_set_menu_item_shortcut(obj, 5, "Oo#o");
	fl_set_menu_item_shortcut(obj, 6, "Pp#p");
	fl_set_menu_item_shortcut(obj, 7, "Ee#e");
	fl_set_menu_item_shortcut(obj, 8, "Uu#u");
	fl_set_menu_item_shortcut(obj, 9, "Ss#s");
	fl_set_menu_item_shortcut(obj, 10, "Aa#a");
	fl_set_menu_item_shortcut(obj, 11, "Tt#t");
	fl_set_menu_item_shortcut(obj, 12, "Xx#x");
	fl_set_menu_item_shortcut(obj, 13, "Gg#g");

	fl_set_object_resize(obj, FL_RESIZE_NONE);
	fl_set_object_gravity(obj, NorthWestGravity, 0);

	obj =
	fl_add_menu(FL_PULLDOWN_MENU, 190, menus_y_offset, 40, 20, "Send");
	menu_send = obj;
	fl_set_object_boxtype(obj, FL_FLAT_BOX);
	fl_set_menu(obj, SEND_MENU);
	fl_set_object_callback(obj, cb_menu_send, 0);

	fl_set_menu_item_shortcut(obj, 1, "Cc#c");
	fl_set_menu_item_shortcut(obj, 2, "Ss#s");
	fl_set_menu_item_shortcut(obj, 3, "Rr#r");
	fl_set_menu_item_shortcut(obj, 4, "Ff#f");
	fl_set_menu_item_shortcut(obj, 5, "Bb#b");
	fl_set_menu_item_shortcut(obj, 6, "Aa#a");

	fl_set_object_resize(obj, FL_RESIZE_NONE);
	fl_set_object_gravity(obj, NorthWestGravity, 0);

	obj =
	fl_add_menu(FL_PULLDOWN_MENU, 250, menus_y_offset, 40, 20, "Misc");
	menu_misc = obj;
	fl_set_object_boxtype(obj, FL_FLAT_BOX);
	fl_set_menu(obj,
				"Address Book|Config Accounts+Misc|Config XFMail Settings|Appearance|Signature|Rules|Retrieve Mail (Alt+N)|Log");
	fl_set_object_callback(obj, cb_menu_misc, 0);
	fl_set_object_shortcut(obj, "#I", 1);

	fl_set_menu_item_shortcut(obj, 1, "Aa#a");
	fl_set_menu_item_shortcut(obj, 2, "Ii#i");
	fl_set_menu_item_shortcut(obj, 3, "Cc#c");
	fl_set_menu_item_shortcut(obj, 4, "Pp#p");
	fl_set_menu_item_shortcut(obj, 5, "Ss#s");
	fl_set_menu_item_shortcut(obj, 6, "Rr#r");
	fl_set_menu_item_shortcut(obj, 7, "mM#m");
	fl_set_menu_item_shortcut(obj, 8, "Ll#l");

	fl_set_object_resize(obj, FL_RESIZE_NONE);
	fl_set_object_gravity(obj, NorthWestGravity, 0);

	obj =
	fl_add_menu(FL_PULLDOWN_MENU, 310, menus_y_offset, 40, 20, "IMAP");
	menu_imap = obj;
	fl_set_object_boxtype(obj, FL_FLAT_BOX);
	fl_clear_menu(obj);
	fl_set_object_callback(obj, cb_menu_imap, 0);
	fl_set_object_shortcut(obj, "#A", 1);

	fl_set_object_resize(obj, FL_RESIZE_NONE);
	fl_set_object_gravity(obj, NorthWestGravity, 0);

	obj =
	fl_add_menu(FL_PULLDOWN_MENU, 725, menus_y_offset, 40, 20, "Help");
	fl_set_object_boxtype(obj, FL_FLAT_BOX);
	fl_set_object_lalign(obj, FL_ALIGN_RIGHT);
	fl_set_menu(obj,
				"Contents|About|Bug report|Subscribe to mailing list|Unsubscribe from mailing list|What's new");
	fl_set_object_callback(obj, cb_menu_help, 0);

	fl_set_menu_item_shortcut(obj, 1, "Cc#c");
	fl_set_menu_item_shortcut(obj, 2, "Aa#a");
	fl_set_menu_item_shortcut(obj, 3, "Bb#b");
	fl_set_menu_item_shortcut(obj, 4, "Ss#s");
	fl_set_menu_item_shortcut(obj, 5, "Uu#u");
	fl_set_menu_item_shortcut(obj, 6, "Ww#w");

	fl_set_object_resize(obj, FL_RESIZE_NONE);
	fl_set_object_gravity(obj, NorthGravity, EastGravity);

	/*
	 * Create button pad.
	 */

	obj =
	fl_add_pixmapbutton(FL_NORMAL_BUTTON, 20, buttons_y_bottom, 35, 33,
						"");
	fl_set_pixmapbutton_data(obj, exit_xpm);
	obj->u_vdata = const_cast < char *>("Exit XFMail");
	fl_set_object_posthandler(obj, post_handler);
	fl_set_object_resize(obj, FL_RESIZE_NONE);
	fl_set_object_gravity(obj, NorthWestGravity, 0);
	fl_set_object_callback(obj, cb_button_exit, 0);
	fl_set_button_shortcut(obj, "^XXx#X", 0);

	obj =
	fl_add_pixmapbutton(FL_NORMAL_BUTTON, 90, buttons_y_bottom, 35, 33,
						"");
	fl_set_pixmapbutton_data(obj, edit_xpm);
	obj->u_vdata = const_cast < char *>("Edit message");
	fl_set_object_posthandler(obj, post_handler);
	fl_set_object_resize(obj, FL_RESIZE_NONE);
	fl_set_object_gravity(obj, NorthWestGravity, 0);
	fl_set_object_callback(obj, cb_button_edit, 0);
	fl_set_button_shortcut(obj, "^EEe#E", 0);

	obj =
	fl_add_pixmapbutton(FL_NORMAL_BUTTON, 125, buttons_y_bottom, 35,
						33, "");
	fl_set_pixmapbutton_data(obj, newmail_xpm);
	obj->u_vdata = const_cast < char *>("Compose new");
	fl_set_object_posthandler(obj, post_handler);
	fl_set_object_resize(obj, FL_RESIZE_NONE);
	fl_set_object_gravity(obj, NorthWestGravity, 0);
	fl_set_object_callback(obj, cb_button_newmail, 0);
	fl_set_button_shortcut(obj, "^CCc#C", 0);

	obj =
	fl_add_pixmapbutton(FL_NORMAL_BUTTON, 175, buttons_y_bottom, 35,
						33, "");
	fl_set_pixmapbutton_data(obj, view_xpm);
	obj->u_vdata = const_cast < char *>("View message");
	fl_set_object_posthandler(obj, post_handler);
	fl_set_object_resize(obj, FL_RESIZE_NONE);
	fl_set_object_gravity(obj, NorthWestGravity, 0);
	fl_set_object_callback(obj, cb_button_view, 0);
	fl_set_button_shortcut(obj, "^VVv#V^M ", 0);

	obj =
	fl_add_pixmapbutton(FL_NORMAL_BUTTON, 210, buttons_y_bottom, 35,
						33, "");
	fl_set_pixmapbutton_data(obj, print_xpm);
	obj->u_vdata = const_cast < char *>("Print message");
	fl_set_object_posthandler(obj, post_handler);
	fl_set_object_resize(obj, FL_RESIZE_NONE);
	fl_set_object_gravity(obj, NorthWestGravity, 0);
	fl_set_object_callback(obj, cb_button_print, 0);
	fl_set_button_shortcut(obj, "^PPp#P", 0);

	obj =
	fl_add_pixmapbutton(FL_NORMAL_BUTTON, 260, buttons_y_bottom, 35,
						33, "");
	fl_set_pixmapbutton_data(obj, reply_xpm);
	obj->u_vdata = const_cast < char *>("Reply to message");
	fl_set_object_posthandler(obj, post_handler);
	fl_set_object_resize(obj, FL_RESIZE_NONE);
	fl_set_object_gravity(obj, NorthWestGravity, 0);
	fl_set_object_callback(obj, cb_button_reply, 0);
	fl_set_button_shortcut(obj, "^RRr#R", 0);

	obj =
	fl_add_pixmapbutton(FL_NORMAL_BUTTON, 295, buttons_y_bottom, 35,
						33, "");
	fl_set_pixmapbutton_data(obj, forward_xpm);
	obj->u_vdata = const_cast < char *>("Forward message");
	fl_set_object_posthandler(obj, post_handler);
	fl_set_object_resize(obj, FL_RESIZE_NONE);
	fl_set_object_gravity(obj, NorthWestGravity, 0);
	fl_set_object_callback(obj, cb_button_forward, 0);
	fl_set_button_shortcut(obj, "^FFf#F", 0);

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

	obj =
	fl_add_pixmapbutton(FL_NORMAL_BUTTON, 381, buttons_y_bottom, 35,
						33, "");
	fl_set_pixmapbutton_data(obj, delete_xpm);
	obj->u_vdata = const_cast < char *>("Delete");
	fl_set_object_posthandler(obj, post_handler);
	fl_set_object_resize(obj, FL_RESIZE_NONE);
	fl_set_object_gravity(obj, NorthWestGravity, 0);
	fl_set_object_callback(obj, cb_button_delete, 0);
	fl_set_button_shortcut(obj, "^DDd#D", 0);

	obj =
	fl_add_pixmapbutton(FL_NORMAL_BUTTON, 430, buttons_y_bottom, 35,
						33, "");
	fl_set_pixmapbutton_data(obj, retr_xpm);
	obj->u_vdata = const_cast < char *>("Check new mail");
	fl_set_object_posthandler(obj, post_handler);
	fl_set_object_resize(obj, FL_RESIZE_NONE);
	fl_set_object_gravity(obj, NorthWestGravity, 0);
	fl_set_object_callback(obj, cb_button_retr, 0);
	fl_set_button_shortcut(obj, "^NNn#N", 0);

	obj =
	fl_add_pixmapbutton(FL_NORMAL_BUTTON, 465, buttons_y_bottom, 35,
						33, "");
	fl_set_pixmapbutton_data(obj, send_xpm);
	obj->u_vdata = const_cast < char *>("Send message");
	fl_set_object_posthandler(obj, post_handler);
	fl_set_object_resize(obj, FL_RESIZE_NONE);
	fl_set_object_gravity(obj, NorthWestGravity, 0);
	fl_set_object_callback(obj, cb_button_send, 0);
	fl_set_button_shortcut(obj, "^KKk#K", 0);

	obj =
	fl_add_pixmapbutton(FL_NORMAL_BUTTON, 515, buttons_y_bottom, 35,
						33, "");
	fl_set_pixmapbutton_data(obj, save_xpm);
	obj->u_vdata = const_cast < char *>("Save message");
	fl_set_object_posthandler(obj, post_handler);
	fl_set_object_resize(obj, FL_RESIZE_NONE);
	fl_set_object_gravity(obj, NorthWestGravity, 0);
	fl_set_object_callback(obj, cb_button_save, 0);
	fl_set_button_shortcut(obj, "^SSs#S", 0);

	obj =
	fl_add_pixmapbutton(FL_NORMAL_BUTTON, 565, buttons_y_bottom, 35,
						33, "");
	fl_set_pixmapbutton_data(obj, abort_xpm);
	obj->u_vdata = const_cast < char *>("Abort");
	fl_set_object_posthandler(obj, post_handler);
	fl_set_object_resize(obj, FL_RESIZE_NONE);
	fl_set_object_gravity(obj, NorthWestGravity, 0);
	fl_set_object_callback(obj, cb_button_abort, 0);
	fl_set_button_shortcut(obj, "^AAa#A", 0);
	abrt = obj;

	obj =
	fl_add_pixmapbutton(FL_NORMAL_BUTTON, 600, buttons_y_bottom, 35,
						33, "");
	fl_set_pixmapbutton_data(obj, help_xpm);
	obj->u_vdata = const_cast < char *>("Help");
	fl_set_object_posthandler(obj, post_handler);
	fl_set_object_resize(obj, FL_RESIZE_NONE);
	fl_set_object_gravity(obj, NorthWestGravity, 0);
	fl_set_object_callback(obj, cb_help_button, 0);
	fl_set_button_shortcut(obj, "^HHh#H", 0);

	inc_timer = obj = fl_add_timer(FL_HIDDEN_TIMER, 0, 0, 1, 2, "");
	fl_set_object_callback(obj, cb_timer, 0);

	send_timer = obj = fl_add_timer(FL_HIDDEN_TIMER, 0, 0, 1, 2, "");
	fl_set_object_callback(obj, cb_send_timer, 0);

	trash_timer = obj = fl_add_timer(FL_HIDDEN_TIMER, 0, 0, 1, 2, "");
	fl_set_object_callback(obj, cb_trash_timer, 0);

	imap_timer = obj = fl_add_timer(FL_HIDDEN_TIMER, 0, 0, 1, 2, "");
	fl_set_object_callback(obj, cb_imap_timer, 0);

	ttip_timer = obj = fl_add_timer(FL_HIDDEN_TIMER, 0, 0, 1, 2, "");
	fl_set_object_callback(obj, cb_ttip_timer, 0);

	pgp_timer = obj = fl_add_timer(FL_HIDDEN_TIMER, 0, 0, 1, 2, "");
	fl_set_object_callback(obj, PGP_Timer_Call, 0);

	if(msgpanesize) {
		preview_timer = obj = fl_add_timer(FL_HIDDEN_TIMER, 0, 0, 1, 2, "");
		fl_set_object_callback(obj, cb_preview_timer, 0);
	}

	fl_end_form();
	return f_mail;
}

int main_close(FL_FORM * form, void *data) {
	if(form == main_form)
		clean_exit(0);

	return FL_IGNORE;
}

void init_forms() {
	choose_init();
	pop_account_init();
	search_init();
	xfm_log_init();
}

char *getmyhostname() {
    string sHostname;
    char * p;
	static char myname[64 + 256] = { '\0'};

	if(strlen(myname) > 1)
		return myname;

	if(Config.exist("hostname")) {
        sHostname = Config.get("hostname", "");
		if(sHostname.find(".") != string::npos) {
			strncpy(myname, sHostname.c_str(), 64 + 256);
			return myname;
		}
		Config.remove("hostname");
	}
	
    if (gethostname(myname, 64+256)==-1) {
        do {
	  	  display_msg(MSG_WARN,
					"XFMail can not determine your host's canonical name!",
					"Make sure that your E-Mail address in Config/Misc dialog is correct");
	  	  
		  p =(char *)fl_show_input("Enter full name of your host (including domain)", myname);

	    } while(!p || !*p || !strchr(p, '.'));

	    strncpy(myname, p, 64 + 256);
	    myname[64 + 256] = '\0';
	}
	
	Config.set("hostname", myname);
	return myname;
}

void Done_Info_Call(FL_OBJECT * obj, long param) {
	char geom[16];

	if(!info_obj)
		return;

	sprintf(geom, "%d %d", info_obj->Help_Form->w, info_obj->Help_Form->h);
	Config.set("infogeom", geom);
	fl_hide_form(info_obj->Help_Form);
	fl_free_form(info_obj->Help_Form);
	fl_free(info_obj);
	info_obj = NULL;

	return;
}

void disp_infowindow(void *ptr, int type) {
	FL_OBJECT *obj;
	char buf[255], *fcc;
	int i, w, h;

	if(!ptr)
		return;

	if(info_obj) {
		fl_activate_form(info_obj->Help_Form);
		XRaiseWindow(fl_display, info_obj->Help_Form->window);
		return;
	}

	info_obj = (FD_Help_Form *) fl_calloc(1, sizeof(FD_Help_Form));

	info_obj->Help_Form = fl_bgn_form(FL_NO_BOX, 430, 290);
	obj = fl_add_box(FL_UP_BOX, 0, 0, 430, 290, "");
	info_obj->Help_Browser = obj =
							 fl_add_browser(FL_NORMAL_BROWSER, 0, 0, 430, 245, "");
	fl_set_object_color(obj, FL_MCOL, FL_YELLOW);
	fl_set_object_lsize(obj, FL_NORMAL_SIZE);
	fl_set_object_gravity(obj, FL_NorthWest, FL_SouthEast);
	fl_set_object_callback(obj, Help_Browser_Call, 0);
	fl_set_browser_hscrollbar(obj, FL_OFF);

	info_obj->Done_Help = obj =
						  fl_add_button(FL_RETURN_BUTTON, 10, 250, 70, 30, "Ok");
	fl_set_object_gravity(obj, FL_SouthWest, FL_NoGravity);
	fl_set_object_resize(obj, FL_RESIZE_NONE);
	fl_set_object_callback(obj, Done_Info_Call, 0);
	fl_end_form();

	Config.setFlags("infogeom", CF_NOTCHANGED);
	w = 400;
	h = 200;
	sscanf(Config.get("infogeom", "").c_str(), "%d %d", &w, &h);
	fl_set_initial_placement(info_obj->Help_Form, main_form->x,
							 main_form->y, w, h);
	fl_set_form_minsize(info_obj->Help_Form, 400, 200);


	switch(type) {
		case INFO_MSG:
			{
				struct _mail_msg *msg = (struct _mail_msg *) ptr;
				struct _mime_msg *mime;
				struct _mime_mailcap *mcap;
				struct _mail_addr *addr;
				struct _news_addr *naddr;

				sprintf(buf, "Message number: %ld", msg->num);
				fl_add_browser_line(info_obj->Help_Browser, buf);
				if(msg->type & M_MH)
					sprintf(buf, "Message type: MH");
				else if(msg->type & M_IMAP)
					sprintf(buf, "Message type: IMAP");
				else if(msg->type & M_NEWS)
					sprintf(buf, "Message type: NEWS");
				else if(msg->type & M_MBOX)
					sprintf(buf, "Message type: MBOX");
				else
					sprintf(buf, "Message type: UNKNOWN");
				fl_add_browser_line(info_obj->Help_Browser, buf);

				if(msg->folder) {
					sprintf(buf, "Located in folder %-.32s (%-.127s)",
							msg->folder->sname ? msg->folder->sname : msg->
							folder->name(msg->folder), msg->folder->fold_path);
					fl_add_browser_line(info_obj->Help_Browser, buf);
				}
				sprintf(buf, "Unique ID in folder: %lu", msg->uid);
				fl_add_browser_line(info_obj->Help_Browser, buf);
				sprintf(buf, "Total length: %lu bytes", msg->msg_len);
				fl_add_browser_line(info_obj->Help_Browser, buf);
				if(msg->msg_body && msg->msg_body_len) {
					sprintf(buf, "%lu bytes of message text are in memory",
							msg->msg_body_len);
					fl_add_browser_line(info_obj->Help_Browser, buf);
				}
				sprintf(buf, "Priority: %d (%s)", get_msg_priority(msg),
						get_msg_priority_name(msg));
				fl_add_browser_line(info_obj->Help_Browser, buf);

				sprintf(buf, "Header information:");
				if(msg->status & H_SHORT) {
					fl_add_browser_line(info_obj->Help_Browser,
										"Only part of the header was in memory (reloaded)");
					my_deactivate();
					set_cursor(main_form, XC_watch);
					msg->get_header(msg);
					set_cursor(main_form, 0);
					my_activate();
				}

				fl_add_browser_line(info_obj->Help_Browser, buf);
				sprintf(buf, " Header length: %d bytes",
						msg->header->header_len);
				fl_add_browser_line(info_obj->Help_Browser, buf);
				sprintf(buf, " Was sent at: %s",
						get_arpa_date(msg->header->snt_time));
				fl_add_browser_line(info_obj->Help_Browser, buf);
				sprintf(buf, " Was received at: %s",
						get_arpa_date(msg->header->rcv_time));
				fl_add_browser_line(info_obj->Help_Browser, buf);
				snprintf(buf, sizeof(buf), " Subject: %s",
						 msg->header->Subject ? msg->header->
						 Subject : "NO SUBJECT");
				fl_add_browser_line(info_obj->Help_Browser, buf);

				addr = msg->header->From;
				if(addr) {
					fl_add_browser_line(info_obj->Help_Browser, " From:");
					i = 0;
					while(addr) {
						fl_add_browser_line(info_obj->Help_Browser,
											get_full_addr_line(addr));
						addr = addr->next_addr;
						i++;
						if(addr && (i > 20)) {
							fl_add_browser_line(info_obj->Help_Browser,
												"  ...");
							break;
						}
					}
				}

				addr = msg->header->To;
				if(addr) {
					fl_add_browser_line(info_obj->Help_Browser, " To:");
					i = 0;
					while(addr) {
						fl_add_browser_line(info_obj->Help_Browser,
											get_full_addr_line(addr));
						addr = addr->next_addr;
						i++;
						if(addr && (i > 20)) {
							fl_add_browser_line(info_obj->Help_Browser,
												"  ...");
							break;
						}
					}
				}

				addr = msg->header->Cc;
				if(addr) {
					fl_add_browser_line(info_obj->Help_Browser, " Cc:");
					i = 0;
					while(addr) {
						fl_add_browser_line(info_obj->Help_Browser,
											get_full_addr_line(addr));
						addr = addr->next_addr;
						i++;
						if(addr && (i > 20)) {
							fl_add_browser_line(info_obj->Help_Browser,
												"  ...");
							break;
						}
					}
				}

				addr = msg->header->Bcc;
				if(addr) {
					fl_add_browser_line(info_obj->Help_Browser, " Bcc:");
					i = 0;
					while(addr) {
						fl_add_browser_line(info_obj->Help_Browser,
											get_full_addr_line(addr));
						addr = addr->next_addr;
						i++;
						if(addr && (i > 20)) {
							fl_add_browser_line(info_obj->Help_Browser,
												"  ...");
							break;
						}
					}
				}

				addr = msg->header->Sender;
				if(addr) {
					fl_add_browser_line(info_obj->Help_Browser, " Sender:");
					i = 0;
					while(addr) {
						fl_add_browser_line(info_obj->Help_Browser,
											get_full_addr_line(addr));
						addr = addr->next_addr;
						i++;
						if(addr && (i > 20)) {
							fl_add_browser_line(info_obj->Help_Browser,
												"  ...");
							break;
						}
					}
				}

				naddr = msg->header->News;
				if(naddr) {
					fl_add_browser_line(info_obj->Help_Browser,
										" Newsgroups:");
					i = 0;
					while(naddr) {
						fl_add_browser_line(info_obj->Help_Browser,
											naddr->name);
						naddr = naddr->next;
						i++;
						if(naddr && (i > 20)) {
							fl_add_browser_line(info_obj->Help_Browser,
												"  ...");
							break;
						}
					}
				}

				fcc = scan_fcc_list(msg, NULL);
				if(fcc) {
					fl_add_browser_line(info_obj->Help_Browser, " Fcc:");
					do {
						fl_add_browser_line(info_obj->Help_Browser, fcc);
						fcc = scan_fcc_list(msg, fcc);
					} while(fcc);
				}

				fl_add_browser_line(info_obj->Help_Browser, "Attributes:");
				if(msg->flags & SIGNED)
					fl_add_browser_line(info_obj->Help_Browser,
										" - Signature attached");
				if(msg->flags & UNREAD)
					fl_add_browser_line(info_obj->Help_Browser, " - Unread");
				if(msg->flags & NOT_SENT)
					fl_add_browser_line(info_obj->Help_Browser,
										" - Scheduled to be sent");
				if(msg->flags & MARKED)
					fl_add_browser_line(info_obj->Help_Browser,
										" - Marked by user");
				if(msg->status & C_DELIVERY)
					fl_add_browser_line(info_obj->Help_Browser,
										" - Needs delivery confirmation");
				if(msg->status & C_READ)
					fl_add_browser_line(info_obj->Help_Browser,
										" - Needs read confirmation");
				if(msg->flags & M_TEMP)
					fl_add_browser_line(info_obj->Help_Browser,
										" - Temporary message (will be deleted after reading)");
				if(msg->flags & H_ONLY)
					fl_add_browser_line(info_obj->Help_Browser,
										" - Message body is on remote server");
				if(msg->flags & ANSWERED)
					fl_add_browser_line(info_obj->Help_Browser,
										" - Reply to the message was sent");
				if(msg->flags & FORWARDED)
					fl_add_browser_line(info_obj->Help_Browser,
										" - Forwarded to other users");
				if(msg->flags & PGP_SIGNED)
					fl_add_browser_line(info_obj->Help_Browser,
										" - Signed with PGP");
				if(msg->flags & PGP_ENCRYPTED)
					fl_add_browser_line(info_obj->Help_Browser,
										" - Encrypted with PGP");
				if(msg->flags & M_SFAILED)
					fl_add_browser_line(info_obj->Help_Browser,
										" - Sending of this message failed");
				if(msg->flags & M_DONTEXPIRE)
					fl_add_browser_line(info_obj->Help_Browser,
										" - Never expires");
				if(msg->status & LOCKED)
					fl_add_browser_line(info_obj->Help_Browser,
										" - Locked (used by viewer/editor)");
				if(msg->status & DELETED)
					fl_add_browser_line(info_obj->Help_Browser,
										" - Deleted or scheduled to be deleted");
				if(msg->status & MOVED)
					fl_add_browser_line(info_obj->Help_Browser,
										" - Scheduled to be moved to another folder");
				if(msg->status & COPIED)
					fl_add_browser_line(info_obj->Help_Browser,
										" - Scheduled to be copied to another folder");
				if(msg->status & CHANGED)
					fl_add_browser_line(info_obj->Help_Browser,
										" - Message text has been modified");
				if(msg->status & S_THREAD)
					fl_add_browser_line(info_obj->Help_Browser,
										" - Message is a head of thread");
				if(msg->status & RECENT)
					fl_add_browser_line(info_obj->Help_Browser,
										" - Newly received message");
				if(msg->status & DELPERM)
					fl_add_browser_line(info_obj->Help_Browser,
										" - Deleted (or scheduled to be deleted) permanently (without moving to trash)");
				if(msg->status & MARKTMP)
					fl_add_browser_line(info_obj->Help_Browser,
										" - Marked by search");
				if(msg->status & MSGNEW)
					fl_add_browser_line(info_obj->Help_Browser,
										" - New message");
				if(msg->status & NOTINCOMING)
					fl_add_browser_line(info_obj->Help_Browser,
										" - Not an incoming message");
				if(msg->status & MMODIFIED)
					fl_add_browser_line(info_obj->Help_Browser, " - Modified");
				if(msg->status & MREFRESH)
					fl_add_browser_line(info_obj->Help_Browser,
										" - Refresh needed");
				if(msg->status & MNOREFRESH)
					fl_add_browser_line(info_obj->Help_Browser,
										" - Don't refresh from server");
				if(msg->status & MOUTGOING)
					fl_add_browser_line(info_obj->Help_Browser,
										" - Outgoing message");
				if(msg->status & MNOTEXISTS)
					fl_add_browser_line(info_obj->Help_Browser,
										" - Does not exists");
				if(msg->status & MTOOBIG)
					fl_add_browser_line(info_obj->Help_Browser,
										" - Message is too large");
				if(msg->status & IMAPDELETED)
					fl_add_browser_line(info_obj->Help_Browser,
										" - Marked as deleted on IMAP server");
				if(msg->status & MTOUS)
					fl_add_browser_line(info_obj->Help_Browser,
										" - Sent directly to us");
				if(msg->status & MFROMUS)
					fl_add_browser_line(info_obj->Help_Browser,
										" - Sent by us");
				sprintf(buf, "Flags: %04X Header: %04X", msg->flags,
						msg->header->flags);
				fl_add_browser_line(info_obj->Help_Browser, buf);

				if(!(msg->flags & H_ONLY))
					mime_scan(msg);
				if(is_mime_msg(msg)) {
					fl_add_browser_line(info_obj->Help_Browser,
										"MIME attachments:");
					mime = msg->mime;
					i = 1;
					while(mime) {
						if(!(mime->flags & ATTACHMENT)) {
							mime = mime->mime_next;
							continue;
						}

						sprintf(buf, " - Attachment #%d", i);
						fl_add_browser_line(info_obj->Help_Browser, buf);
						if(mime->m_start < mime->m_end) {
							sprintf(buf, " Start offset: %lu bytes",
									mime->m_start);
							fl_add_browser_line(info_obj->Help_Browser, buf);
							sprintf(buf, " End offset: %lu bytes",
									mime->m_end);
							fl_add_browser_line(info_obj->Help_Browser, buf);
							sprintf(buf, " Total length: %lu bytes",
									mime->m_end - mime->m_start);
							fl_add_browser_line(info_obj->Help_Browser, buf);
						}

						if(mime->src_info) {
							snprintf(buf, sizeof(buf),
									 " File to be attached: %s",
									 mime->src_info);
							fl_add_browser_line(info_obj->Help_Browser, buf);
						}

						if(mime->mailcap) {

							if((mcap = find_mailcap(mime->mailcap->type_text,
													mime->mailcap->
													subtype_text, 2)) == NULL)
								mcap = mime->mailcap;

							snprintf(buf, sizeof(buf),
									 " Attachment type: %s/%s",
									 mime->mailcap->type_text,
									 mime->mailcap->subtype_text);
							fl_add_browser_line(info_obj->Help_Browser, buf);
							if(mcap != mime->mailcap) {
								snprintf(buf, sizeof(buf),
										 " WARNING: Supported through: %s/%s",
										 mcap->type_text, mcap->subtype_text);
								fl_add_browser_line(info_obj->Help_Browser,
													buf);
							}
							sprintf(buf, " Can view using internal viewer: %s",
									(mcap->view
									 || mcap->process) ? "YES" : "NO");
							fl_add_browser_line(info_obj->Help_Browser, buf);
							sprintf(buf, " Can view using external viewer: %s",
									mcap->ext_mcap ? "YES" : "NO");
							fl_add_browser_line(info_obj->Help_Browser, buf);
							sprintf(buf, " Can print: %s",
									mcap->print ? "YES" : "NO");
							fl_add_browser_line(info_obj->Help_Browser, buf);
						}

						if(mime->encoding) {
							sprintf(buf, " Encoding: %s",
									mime->encoding->encoding_name);
							fl_add_browser_line(info_obj->Help_Browser, buf);
						}

						if(mime->charset) {
							sprintf(buf, " Charset: %s (%s)",
									mime->charset->charset_name,
									mime->charset->charset_descr);
							fl_add_browser_line(info_obj->Help_Browser, buf);
						}

						if(mime->c_id) {
							snprintf(buf, sizeof(buf), " %s: %s", MIME_C_ID,
									 mime->c_id);
							fl_add_browser_line(info_obj->Help_Browser, buf);
						}

						if(mime->c_descr) {
							snprintf(buf, sizeof(buf), " %s: %s", MIME_C_DESCR,
									 mime->c_descr);
							fl_add_browser_line(info_obj->Help_Browser, buf);
						}

						if(mime->c_len) {
							sprintf(buf, " %s: %lu", MIME_C_LENGTH,
									mime->c_len);
							fl_add_browser_line(info_obj->Help_Browser, buf);
						}

						if(mime->boundary) {
							snprintf(buf, sizeof(buf),
									 " Multipart boundary: %s",
									 mime->boundary);
							fl_add_browser_line(info_obj->Help_Browser, buf);
						}

						mime = mime->mime_next;
						i++;
					}
				}
				fl_show_form(info_obj->Help_Form, FL_PLACE_FREE, FL_TRANSIENT,
							 "Message info");
			}
			break;

		case INFO_FOLDER:
			{
				struct _mail_folder *fld = (struct _mail_folder *) ptr;

				sprintf(buf, "Folder short name: %s",
						fld->sname ? fld->sname : (fld->name) (fld));
				fl_add_browser_line(info_obj->Help_Browser, buf);
				if(fld->descr) {
					snprintf(buf, sizeof(buf), "Folder description: %s",
							 fld->descr);
					fl_add_browser_line(info_obj->Help_Browser, buf);
				}
				if(fld->type & F_MH)
					sprintf(buf, "Folder type: MH");
				else if(fld->type & F_IMAP)
					sprintf(buf, "Folder type: IMAP");
				else if(fld->type & F_NEWS)
					sprintf(buf, "Folder type: NEWS");
				else if(fld->type & F_MBOX)
					sprintf(buf, "Folder type: MBOX");
				else
					sprintf(buf, "Folder type: UNKNOWN");
				fl_add_browser_line(info_obj->Help_Browser, buf);
				if(fld->spec) {
					fl_add_browser_line(info_obj->Help_Browser,
										"Type specific info:");
					if(fld->type & F_MBOX) {
						sprintf(buf, "Processed folder size: %d",
								((struct _mbox_spec *) fld->spec)->fsize);
						fl_add_browser_line(info_obj->Help_Browser, buf);
						if(((struct _mbox_spec *) fld->spec)->ffd)
							sprintf(buf, "Opened with mode: %s",
									((struct _mbox_spec *) fld->spec)->mode);
						else
							sprintf(buf, "Not opened");
						fl_add_browser_line(info_obj->Help_Browser, buf);
					} else if(fld->type & F_IMAP) {
						snprintf(buf, sizeof(buf), "Located on host: %s/%s",
								 ((struct _imap_src *) fld->spec)->hostname,
								 ((struct _imap_src *) fld->spec)->service);
						fl_add_browser_line(info_obj->Help_Browser, buf);
						sprintf(buf, "Connected as username: %s",
								((struct _imap_src *) fld->spec)->username);
						fl_add_browser_line(info_obj->Help_Browser, buf);
					}
				}
				snprintf(buf, sizeof(buf), "Folder path: %s", fld->fold_path);
				fl_add_browser_line(info_obj->Help_Browser, buf);
				sprintf(buf, "Total messages: %ld", fld->num_msg);
				fl_add_browser_line(info_obj->Help_Browser, buf);
				sprintf(buf, "Total unread messages: %ld", fld->unread_num);
				fl_add_browser_line(info_obj->Help_Browser, buf);
				sprintf(buf, "Hierarchy delimiter: %c", fld->hdelim);
				fl_add_browser_line(info_obj->Help_Browser, buf);
				sprintf(buf, "Unique ID: %ld", fld->getuid(fld));
				fl_add_browser_line(info_obj->Help_Browser, buf);
				if(fld->color != -1) {
					sprintf(buf, "Color: %d", fld->color);
					fl_add_browser_line(info_obj->Help_Browser, buf);
				}
				if(fld->sort != -1) {
					sprintf(buf, "Sort: %d", fld->sort);
					fl_add_browser_line(info_obj->Help_Browser, buf);
				}
				if(fld->expire > 0) {
					sprintf(buf, "Delete messages older then %d days",
							fld->expire);
					fl_add_browser_line(info_obj->Help_Browser, buf);
				}

				if(fld->From) {
					snprintf(buf, sizeof(buf), "Default From: %s",
							 get_full_addr_line(fld->From));
					fl_add_browser_line(info_obj->Help_Browser, buf);
				}

				if(fld->To) {
					snprintf(buf, sizeof(buf), "Default To: %s",
						get_full_addr_line(fld->To));
					fl_add_browser_line(info_obj->Help_Browser, buf);
				}

				if(fld->pfold) {
					snprintf(buf, sizeof(buf), "Subfolder of: %s",
							 fld->pfold->fold_path);
					fl_add_browser_line(info_obj->Help_Browser, buf);
					sprintf(buf, "Nesting level: %d", fld->level + 1);
					fl_add_browser_line(info_obj->Help_Browser, buf);
				}

				if(fld->subfold) {
					for(i = 0; i < MAX_SUBFOLDERS; i++) {
						if(fld->subfold[i]) {
							snprintf(buf, sizeof(buf), "Parent of: %s",
								 	fld->subfold[i]->fold_path);
							fl_add_browser_line(info_obj->Help_Browser, buf);
						}
					}
				}

				fl_add_browser_line(info_obj->Help_Browser, "Attributes:");
				if(fld->status & SYSTEM)
					fl_add_browser_line(info_obj->Help_Browser,
										" - System folder (can not be deleted or renamed)");
				if(fld->status & SORTED)
					fl_add_browser_line(info_obj->Help_Browser,
										" - Messages are sorted");
				if(fld->status & OPENED)
					fl_add_browser_line(info_obj->Help_Browser, " - Opened");
				if(fld->status & SEARCH)
					fl_add_browser_line(info_obj->Help_Browser,
										" - Contains messages found by search");
				if(fld->flags & CACHED)
					fl_add_browser_line(info_obj->Help_Browser, " - Cached");
				if(fld->status & FRONLY)
					fl_add_browser_line(info_obj->Help_Browser,
										" - Read-only");
				if(fld->status & NOINFR)
					fl_add_browser_line(info_obj->Help_Browser,
										" - Can not have subfolders");
				if(fld->status & FHIDDN)
					fl_add_browser_line(info_obj->Help_Browser,
										" - Hidden (how can you see this?)");
				if(fld->status & NOTRASH)
					fl_add_browser_line(info_obj->Help_Browser,
										" - Trash folder");
				if(fld->status & FRESCAN)
					fl_add_browser_line(info_obj->Help_Browser,
										" - Should be rescanned");
				if(fld->status & FSHORTH)
					fl_add_browser_line(info_obj->Help_Browser,
										" - Scan short headers");
				if(fld->flags & FNCOUNT)
					fl_add_browser_line(info_obj->Help_Browser,
										" - Unread messages not counted in total");
				if(fld->flags & FMARKED)
					fl_add_browser_line(info_obj->Help_Browser, " - Marked");
				if(fld->status & FMRKTMP)
					fl_add_browser_line(info_obj->Help_Browser,
										" - Marked temporarily");
				if(fld->status & FRECNT)
					fl_add_browser_line(info_obj->Help_Browser,
										" - Contains new messages");
				if(fld->flags & FSHRECP)
					fl_add_browser_line(info_obj->Help_Browser,
										" - Show recipient");
				if(fld->status & FUNREAD)
					fl_add_browser_line(info_obj->Help_Browser,
										" - Only unread messages shown");
				if(fld->flags & FCHECK)
					fl_add_browser_line(info_obj->Help_Browser,
										" - Check periodically");
				if(fld->status & FREMOTE)
					fl_add_browser_line(info_obj->Help_Browser,
										" - Remote folder");
				else
					fl_add_browser_line(info_obj->Help_Browser,
										" - Local folder");
				if(fld->status & FLOCKED)
					fl_add_browser_line(info_obj->Help_Browser, " - Locked");
				if(fld->status & FREWRTE)
					fl_add_browser_line(info_obj->Help_Browser,
										" - Will be rewritten");
				if(fld->status & FNOCLSE)
					fl_add_browser_line(info_obj->Help_Browser,
										" - Can not be closed");
				if(fld->status & FDUMMY)
					fl_add_browser_line(info_obj->Help_Browser,
										" - Dummy folder");
				if(fld->flags & FEXPND)
					fl_add_browser_line(info_obj->Help_Browser,
										" - Show subfolders");
				if(fld->status & FSKIP)
					fl_add_browser_line(info_obj->Help_Browser,
										" - Don't show in folder list");
				if(fld->status & FALIAS)
					fl_add_browser_line(info_obj->Help_Browser,
										" - Short name is an alias");
				if(fld->status & FNSCAN)
					fl_add_browser_line(info_obj->Help_Browser,
										" - Don't rescan");
				if(fld->status & FEXPNG)
					fl_add_browser_line(info_obj->Help_Browser,
										" - EXPUNGE pending");
				if(fld->flags & FRKEEP)
					fl_add_browser_line(info_obj->Help_Browser,
										" - Keep reply messages");
				if(fld->flags & FNVALD)
					fl_add_browser_line(info_obj->Help_Browser,
										" - Don't validate messages");
				if(fld->status & FNOMOD)
					fl_add_browser_line(info_obj->Help_Browser,
										" - Don't modify during session");
				if(fld->status & FTOP)
					fl_add_browser_line(info_obj->Help_Browser,
										" - Top folder");
				if(fld->status & FSUBS)
					fl_add_browser_line(info_obj->Help_Browser,
										" - Subscribed");
				fl_show_form(info_obj->Help_Form, FL_PLACE_FREE, FL_TRANSIENT,
							 "Folder info");
			}
			break;

		default:
			fl_free_form(info_obj->Help_Form);
			fl_free(info_obj);
			info_obj = NULL;
			break;
	}

	return;
}

int msg_preview_mimecb(void *ob, TextLine * line, int key, int data) {
	struct _mime_msg *mime;
	struct _mime_mailcap *mc, *mcold;
	int apup;

	mime = current_message->mime;
	while(mime && data) {
		if(!(mime->flags & ATTACHMENT) || (mime->flags & TEXT_PART)) {
			mime = mime->mime_next;
			continue;
		}

		if(--data == 0)
			break;
		mime = mime->mime_next;
	}

	if(mime == NULL)
		return 1;

	switch(key) {
		case 1:
			my_deactivate();
			set_cursor(main_form, XC_watch);
			view_part(current_message, mime);
			set_cursor(main_form, 0);
			my_activate();
			break;

		case 2:
			my_deactivate();
			set_cursor(main_form, XC_watch);
			if((mc = mcap_select(mime->mailcap->type_text,
								 mime->mailcap->subtype_text)) != NULL) {
				mcold = mime->mailcap;
				mime->mailcap = mc;
				view_part(current_message, mime);
				mime->mailcap = mcold;
			}
			set_cursor(main_form, 0);
			my_activate();
			break;

		case 3:
			apup = fl_defpup(main_form->window, "Attachment%t|Save|Print");
			switch(fl_dopup(apup)) {
				case 1:
					my_deactivate();
					set_cursor(main_form, XC_watch);
					save_part(current_message, mime, NULL, 0);
					set_cursor(main_form, 0);
					my_activate();
					break;

				case 2:
					my_deactivate();
					set_cursor(main_form, XC_watch);
					if(mime->mailcap->print)
						(*mime->mailcap->print) (current_message, mime);
					else
						display_msg(MSG_WARN, "Don't know how to print", "%s/%s",
									mime->mailcap->type_text,
									mime->mailcap->subtype_text);
					set_cursor(main_form, 0);
					my_activate();
					break;
			}
			fl_freepup(apup);
			break;
	}

	return 0;
}

int msg_preview_addr(char *prefix, mail_addr * addr) {
	int chset;

	while(addr) {
		fl_add_textedit_line(msgpane,
							 get_charset_addr_line(prefix, addr, &chset));
		prefix = " ";
		addr = addr->next_addr;
	}

	return 0;
}

int msg_preview_header(struct _mail_msg *msg) {
	head_field *hf;
	char buf[255];
	struct _news_addr *naddr;
	int i;
	int col = Config.getInt("headcolor", FL_BLUE);
#ifdef HAVE_REGCOMP
	int showurl;
	struct _url_spec *url = NULL;
	showurl = Config.getInt("showurl", 0);
#endif

	hf = msg->header->other_fields;
	while(hf) {
		snprintf(buf, sizeof(buf), "%s: %s", hf->f_name, hf->f_line);
		fl_add_textedit_line(msgpane, buf);

#ifdef HAVE_REGCOMP
		url = highlight_urls(buf);
		if (url != NULL) {
			int linenum;

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

	snprintf(buf, sizeof(buf), "Date: %s",
			 get_arpa_date(msg->header->snt_time));
	fl_add_textedit_line(msgpane, buf);
	snprintf(buf, sizeof(buf), "%s: %04X", STATUS_FIELD,
			 msg->flags & 0xFFFF);
	fl_add_textedit_line(msgpane, buf);

	msg_preview_addr("Sender: ", msg->header->Sender);
	msg_preview_addr("From: ", msg->header->From);
	msg_preview_addr("To: ", msg->header->To);

	if(msg->header->News) {
		snprintf(buf, sizeof(buf), "Newsgroups: %s",
				 msg->header->News->name);
		fl_add_textedit_line(msgpane, buf);
		naddr = msg->header->News->next;
		while(naddr) {
			snprintf(buf, sizeof(buf), " %s", naddr->name);
			fl_add_textedit_line(msgpane, buf);
			naddr = naddr->next;
		}
	}

	if(msg->header->Subject) {
		snprintf(buf, sizeof(buf), "Subject: %s",
				 rfc1522_decode(msg->header->Subject, &i));
		fl_add_textedit_line(msgpane, buf);
	}

	msg_preview_addr("Cc: ", msg->header->Cc);
	msg_preview_addr("Bcc: ", msg->header->Bcc);
	fl_add_textedit_line(msgpane, "");

	for(i = 0; i < fl_get_textedit_maxline(msgpane); i++)
		fl_set_textedit_line_color(msgpane, i, -1, col);

	return 0;
}

int msg_preview(struct _mail_msg *msg) {
	struct _mime_msg *mime;
	struct _pop_src *popsrc;
	struct _retrieve_src *msgsrc;
	char buf[255], prefix[17], *p, *p1, *mname;
	int wascr, i, markincl, showurl, linenum, ttop = 0;
	int tlines = 0, tsize = 0;
	struct _url_spec *url, *urls;
	head_field *hf;

	if(msgpane == NULL)
		return 0;

	if(msg == NULL) {
		fl_clear_textedit(msgpane);
		return 0;
	}

	fl_set_timer(preview_timer, Config.getInt("previewtime", 2));
	fl_freeze_form(main_form);
	fl_clear_textedit(msgpane);

	if(msg->status & MNOTEXISTS) {
		fl_add_textedit_line(msgpane, "MESSAGE NO LONGER EXISTS");
		fl_set_textedit_line_color(msgpane,
								   fl_get_textedit_maxline(msgpane) - 1,
								   FL_WHITE, FL_RED);
		fl_unfreeze_form(main_form);
		return -1;
	}

	if(Config.getInt("sheader", 0)) {
		fl_set_textedit_vscrollbar(msgpane, 1);
		if(msg->flags & H_ONLY) {
			if(((msgsrc = get_msg_src(msg)) != NULL)
			   && msgsrc->flags & RSRC_DOWNLOAD) {
				set_cursor(main_form, XC_watch);
				my_deactivate();
				if(msg->type & M_IMAP)
					msg->get_file(msg);
				else if((popsrc = get_msg_popsrc(msg)) != NULL)
					pop_getfull_msg(popsrc, msg);
				my_activate();
				set_cursor(main_form, 0);
			} else {
				if(!(msg->type & M_IMAP))
					msg->get_header(msg);
				msg_preview_header(msg);
				fl_add_textedit_line(msgpane,
									 "MESSAGE BODY RESIDES ON THE REMOTE SERVER");
				fl_set_textedit_line_color(msgpane,
										   fl_get_textedit_maxline(msgpane)
										   - 1, FL_WHITE, FL_RED);
				fl_set_textedit_topline(msgpane,
										fl_get_textedit_maxline(msgpane) -
										1);
				fl_set_textedit_fontsize(msgpane,
					charset_size_from_code(supp_charsets[DEFAULT_CHARSET].charset_code));
				fl_set_textedit_fontstyle(msgpane,
					charset_style_from_code(supp_charsets[DEFAULT_CHARSET].charset_code));
				fl_unfreeze_form(main_form);
				return 0;
			}
		}
		msg->get_header(msg);
		msg_preview_header(msg);
		ttop = fl_get_textedit_maxline(msgpane);
	} else {
		if(msg->flags & H_ONLY) {
			if(((msgsrc = get_msg_src(msg)) != NULL)
			   && msgsrc->flags & RSRC_DOWNLOAD) {
				set_cursor(main_form, XC_watch);
				my_deactivate();
				if(msg->type & M_IMAP)
					msg->get_file(msg);
				else if((popsrc = get_msg_popsrc(msg)) != NULL)
					pop_getfull_msg(popsrc, msg);
				my_activate();
				set_cursor(main_form, 0);
			} else {
				fl_add_textedit_line(msgpane,
									 "MESSAGE BODY RESIDES ON THE REMOTE SERVER");
				fl_set_textedit_line_color(msgpane,
										   fl_get_textedit_maxline(msgpane)
										   - 1, FL_WHITE, FL_RED);
				fl_unfreeze_form(main_form);
				return 0;
			}
		}
	}

	if(msg->flags & UNREAD) {
		if((hf = need_read_confirm(msg)) != NULL) {
			fl_unfreeze_form(main_form);
			switch(Config.getInt("vconfirm", 1)) {
				case 2:
					if(!display_msg
					   (MSG_QUEST, "Confirm reading",
						"Send confirmation to %s?", hf->f_line)) {
						delete_read_confirm(msg);
						break;
					}
				case 1:
					set_cursor(main_form, XC_watch);
					my_deactivate();
					read_confirm(msg);
					my_activate();
					set_cursor(main_form, 0);
					break;
			}
			fl_freeze_form(main_form);
		}

		i = Config.getInt("previewtime", 0);
		if(i == 0) {
			msg->flags &= ~UNREAD;
			msg->update(msg);
			redraw_msg(msg);
			if(msg->folder->unread_num)
				msg->folder->unread_num--;
			update_title();
			redraw_fld_line(msg->folder);
		} else {
			if(i != PREVIEW_MAX_TIMER)
				fl_set_timer(preview_timer, i);
		}
	}

	mime = get_view_part(msg);
	if(mime && mime->charset &&
	   (mime->charset->charset_code != CHAR_UNKNOWN)) {
		fl_set_textedit_fontsize(msgpane, charset_size_from_code(mime->charset->charset_code));
		fl_set_textedit_fontstyle(msgpane, charset_style_from_code(mime->charset->charset_code));
	} else {
		fl_set_textedit_fontsize(msgpane,
			charset_size_from_code(supp_charsets[DEFAULT_CHARSET].charset_code));
		fl_set_textedit_fontstyle(msgpane,
			charset_style_from_code(supp_charsets[DEFAULT_CHARSET].charset_code));
	}

	if(mime && ((mime->flags & PREAMBLE) || (mime->flags & EPILOG)))
		mime = NULL;

	if(mime == NULL) {
		fl_add_textedit_line(msgpane, "NO TEXT TO PREVIEW");
		fl_set_textedit_line_color(msgpane,
								   fl_get_textedit_maxline(msgpane) - 1,
								   FL_WHITE, FL_RED);
		fl_set_textedit_topline(msgpane,
								fl_get_textedit_maxline(msgpane) - 1);
		goto show_mime;
	}

	if(msg->get_text(msg, mime) != 0) {
		fl_unfreeze_form(main_form);
		return -1;
	}

	if((mime = get_view_part(msg)) == NULL) {
		fl_unfreeze_form(main_form);
		return -1;
	}

	if((markincl = Config.getInt("markincl", 0)) != 0)
		strncpy(prefix, Config.get("prefix", ">").c_str(), 16);
	showurl = Config.getInt("showurl", 0);
	msg_seek(NULL, mime->m_start, SEEK_SET);
	if(mime->boundary && (mime->flags & (TEXT_PART | ATTACHMENT))) {
		while(msg_gets(buf, 255, NULL)) {
			strip_newline(buf);
			if(strlen(buf) < 1)
				break;
		}
	} else if(mime->boundary && (mime->flags & EPILOG))
		msg_gets(buf, 255, NULL);

	wascr = 1;
	(*mime->encoding->ce_dec) (NULL, &i);
	while((wascr >= 0) &&
		  (msg_tell(NULL) < mime->m_end) && msg_gets(buf, 255, NULL)) {
		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++;
			}

			linenum = fl_get_textedit_maxline(msgpane);
			if(wascr)
				fl_add_textedit_line(msgpane, p1);
			else
				fl_append_to_textedit_line(msgpane, -1, p1);

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

					if(*mname == '>')
						fl_set_textedit_line_color(msgpane, linenum, -1,
												   markincl);
				}
			}
#ifdef  HAVE_REGCOMP
			if(showurl &&
			   ((urls
				 =
				 highlight_urls(fl_get_textedit_line(msgpane, linenum)))
				!= NULL)) {
				url = urls;
				while(url) {
					fl_set_textedit_blockattr(msgpane, 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

			tlines++;
			tsize += strlen(p1);

			if((tlines > MAX_PREVIEW_LINES) || (tsize > MAX_PREVIEW_SIZE)) {
				(*mime->encoding->ce_dec) (NULL, &i);
				wascr = -1;
				fl_add_textedit_line(msgpane,
									 "CAN NOT PREVIEW THE WHOLE MESSAGE");
				fl_set_textedit_line_color(msgpane,
										   fl_get_textedit_maxline(msgpane)
										   - 1, FL_WHITE, FL_RED);
				break;
			}

			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(msgpane, p);
	}

	show_mime:
	i = 0;
	mime = msg->mime;
	while(mime) {
		if(!(mime->flags & ATTACHMENT) || (mime->flags & TEXT_PART)) {
			mime = mime->mime_next;
			continue;
		}
		if(i++ == 0) {
			fl_add_textedit_line(msgpane, "");
			fl_add_textedit_line(msgpane, "MIME attachments:");
			fl_set_textedit_line_color(msgpane,
									   fl_get_textedit_maxline(msgpane) -
									   1, FL_WHITE, FL_RED);
		}
		fl_add_textedit_line(msgpane, get_mime_line(i, msg, mime));
		fl_set_textedit_line_color(msgpane,
								   fl_get_textedit_maxline(msgpane) - 1,
								   FL_WHITE, FL_RED);
		fl_textedit_setline_callback(msgpane,
									 fl_get_textedit_maxline(msgpane) - 1,
									 msg_preview_mimecb,
									 FL_TEXTLINE_CLK_CALLBACK, i);
		mime = mime->mime_next;
	}

	if(ttop)
		fl_set_textedit_topline(msgpane, ttop);

	msg->free_text(msg);
	fl_unfreeze_form(main_form);

	return 0;
}

int main(int argc, char **argv) {
	int i, cnfdir = 0, havemail = 0;
	int x, y;
	unsigned int w, h;
	char menu[255];
	char from[255], cfgfile[255] = "", buf[512];
	char gecos[32];
	char *p;
	struct passwd *pwd;
	struct stat sb;
	DIR *dirp;
	Display *pDisplay;
	Window root;
	struct _mail_addr *addr;
	struct _imap_src *imap;
	list<struct _retrieve_src>::iterator pi;

#if defined WITH_THREADS
    int iXinitThreadsRc = XInitThreads();

    if(iXinitThreadsRc == 0) {
        cerr << "Thread init failed!" << endl;
    } else {
        cerr << "Threads Initialized!!" << endl;
    }
#endif

	fl_library_version(&xforms_version, &xforms_revision);

	printf("XFMail %s%s - X11 e-mail client for %s.\n", VERSION, DEBUGVERSION, XF_OS);
	printf("(C) 2003 XFMail/Archimedes Development Team\n");

	for(i = 1; i < argc; i++) {
		if(*argv[i] != '-')
			continue;

		if(!strcmp(argv[i] + 1, "help") ||
		   !strcmp(argv[i] + 1, "h") || !strcmp(argv[i] + 1, "?"))
			usage(argv[0], 1);

		if(strcmp(argv[i] + 1, "cfgfile") == 0) {
			if(++i == argc)
				usage(argv[0], 1);
			strncpy(cfgfile, argv[i], 254);
			configdir[254] = '\0';
			continue;
		}

		if(strcmp(argv[i] + 1, "cfgdir") == 0) {
			if(++i == argc)
				usage(argv[0], 1);
			strncpy(configdir, argv[i], 254);
			configdir[254] = '\0';
			continue;
		}

		if(strcmp(argv[i] + 1, "readonly") == 0) {
			readonly = 1;
			continue;
		}
	}

	umask(077);
	p = getenv("TMPDIR");
	strcpy(tmpdir, p ? p : "/tmp");

	signal(SIGHUP, SIG_IGN);
	signal(SIGQUIT, SIG_IGN);
	signal(SIGPIPE, SIG_IGN);

#ifndef DEBUG
	signal(SIGSEGV, crash_handle);
	signal(SIGBUS, crash_handle);
#endif

#ifdef  HAVE_SETLOCALE
	if(setlocale(LC_ALL, "") == NULL) {
		fprintf(stderr, "Locale isn't supported\n");
		if(setlocale(LC_ALL, NULL) == NULL) {
			fprintf(stderr, "setlocale() failed, can not continue\n");
			exit(1);
		}
		fprintf(stderr, "Using %s locale instead.\n",
				setlocale(LC_CTYPE, NULL));
	}
	#ifdef  HAVE_XSUPPORTSLOCALE
	if(!XSupportsLocale())
		fprintf(stderr, "WARNING: Xlib: locale %s not supported\n.",
				setlocale(LC_CTYPE, NULL));
	else {
		if(XSetLocaleModifiers("") == NULL)
			fprintf(stderr, "WARNING: Cannot set locale modifiers.\n");
	}
	#endif

#endif

	setpwent();
	if((pwd = getpwuid(getuid())) == NULL)
		fprintf(stderr,
				"WARNING: Can not access your password entry. Who are you?\n");

	p = getenv("USER");
	if(!p && !pwd) {
		fprintf(stderr,
				"Can not determine your username (set USER environment variable to fix this)\n");
		exit(1);
	}
	strncpy(user_n, p ? p : pwd->pw_name, 31);

	p = getenv("HOME");
	if(!p && !pwd) {
		fprintf(stderr,
				"Can not determine your home directory (set HOME environment variable to fix this)\n");
		exit(1);
	}
	strncpy(homedir, p ? p : pwd->pw_dir, 240);
	gecos[0] = '\0';
	strncpy(gecos, pwd ? pwd->pw_gecos : user_n, 31);
	gecos[31] = '\0';
	user_n[31] = '\0';
	homedir[240] = '\0';
	for(i = 0; i < strlen(gecos); i++) {
		if(!isgraph(gecos[i]) && (gecos[i] != ' ')) {
			gecos[i] = '\0';
			break;
		}
	}

	if(!*configdir) {
		if((p = getenv("XFMAILDIR")) != NULL)
			strncpy(configdir, p, 254);
		else
			snprintf(configdir, sizeof(configdir), "%s/.xfmail", homedir);
		configdir[254] = '\0';
	}

	if(stat(configdir, &sb) == -1) {
		if(mkdir(configdir, 0700) == -1) {
			fprintf(stderr, "init: can not create %s", configdir);
			exit(1);
		}

		cnfdir = 1;
	} else {
		if(!(sb.st_mode & S_IFDIR)) {
			fprintf(stderr, "init: %s is not a directory", configdir);
			exit(1);
		}
	}

	if(!(dirp = opendir(configdir))) {
		fprintf(stderr, "init: can not access %s", configdir);
		exit(1);
	}

	closedir(dirp);

	snprintf(buf, sizeof(buf), "%s/.xfmrules", homedir);
	if(stat(buf, &sb) == 0) {
		cnfdir = 2;
		snprintf(from, sizeof(from), "%s/.xfmrules", configdir);
		do_move(buf, from);

		snprintf(from, sizeof(from), "%s/.xfmailrc", homedir);
		snprintf(buf, sizeof(buf), "%s/.xfmailrc", configdir);
		do_move(from, buf);

		snprintf(from, sizeof(from), "%s/.xfmime", homedir);
		snprintf(buf, sizeof(buf), "%s/.xfmime", configdir);
		do_move(from, buf);

		snprintf(from, sizeof(from), "%s/.xfdefaults", homedir);
		snprintf(buf, sizeof(buf), "%s/.xfdefaults", configdir);
		do_move(from, buf);

	}

	p = *cfgfile ? cfgfile : getenv("XFMAILRC");
	snprintf(conf_name, sizeof(conf_name), "%s/%s", configdir,
			 p ? p : ".xfmailrc");

	if(Config.load(conf_name) < 0)
		fprintf(stderr, "init: Can not load configuration file %s",
				conf_name);

	Config.read_xfdefaults();

	if(!fl_initialize(&argc, argv, "XFMail", xfmail_cmdopt, Ncopt)) {
		fprintf(stderr, "Failed to initialize display\n");
		exit(1);
	}

	if(xforms_revision == 89)
		fl_show_alert("WARNING, version 0.89 of XForms has been known to cause problems!",
					  "Please remove your current version of XForms",
					  "and install XForms version 0.88 or >=1.0",
					   1);

	XSetErrorHandler(x11error_handle);
	XSetIOErrorHandler(x11ioerror_handle);

	fl_get_app_resources(xfres, Nropt);
	fl_set_app_nomainform(1);

	for(i = 1; i < argc; i++) {
		if(*argv[i] == '-')
			continue;
		xfcompose = 1;
	}

	init = 1;

	if(Config.exist("from"))
		Config.check_version();
	pDisplay = FL_ObjectDisplay(fl_default_window());
	root = RootWindowOfScreen(DefaultScreenOfDisplay(pDisplay));

	XpmCreatePixmapFromData(pDisplay, root, icon_mail_xpm,
							&iconPix, &iconPix_sh, NULL);
	XpmCreatePixmapFromData(pDisplay, root, icon_nomail_xpm,
							&iconPix_noMail, &iconPix_noMail_sh, NULL);
	XpmCreatePixmapFromData(pDisplay, root, mail_edit,
							&icon_MailEdit, &icon_MailEdit_sh, NULL);
	XpmCreatePixmapFromData(pDisplay, root, abook_xpm,
							&icon_ABook, &icon_ABook_sh, NULL);
	mailcur = fl_create_bitmap_cursor(mailcur_bits, mailcur_mask_bits,
									  mailcur_width, mailcur_height,
									  mailcur_width / 2, 0);

	restore_fonts();
	restore_charsets();

	fl_set_goodies_font(Config.getInt("GoodiesFontFStyle",
							   FL_NORMAL_STYLE), Config.getInt("GoodiesFontFSize",
															   FL_DEFAULT_SIZE));
	if(xfdefs.popfsize > 0)
		fl_setpup_fontsize(xfdefs.popfsize);
	if(xfdefs.popfstyle > 0)
		fl_setpup_fontstyle(xfdefs.popfstyle);
	if(xfdefs.popcursor > 0)
		fl_setpup_default_cursor(xfdefs.popcursor);
	if((xfdefs.popbgcol > 0) && (xfdefs.popfgcol > 0))
		fl_setpup_color(xfdefs.popbgcol, xfdefs.popfgcol);
	else if(xfdefs.popbgcol > 0)
		fl_setpup_color(xfdefs.popbgcol, FL_BLACK);
	else if(xfdefs.popfgcol > 0)
		fl_setpup_color(FL_COL1, xfdefs.popfgcol);

	fbrowsersize = Config.getInt("fbrowser", 180);
	if((fbrowsersize < 80) || (fbrowsersize > 300))
		fbrowsersize = 180;
	Config.setFlags("fbrowser", CF_NOTCHANGED);
	msgpanesize = Config.getInt("msgpane", 0);
	if((msgpanesize < 40) || (msgpanesize > 800))
		msgpanesize = 0;
	Config.setFlags("msgpane", CF_NOTCHANGED);

	init_forms();
	init_procs();

	init_coders(); //Init the encode/decode buffers

#ifdef USE_GPASSWD
	if(Config.getInt("use_gpasswd", 0) != 0)	//Use it if found in cfgfile
		set_passphrase();
#endif

	if(xfcompose) {
		nomainwindow = 1;
		startup = STARTUP_COMPOSE;
	}

	if(!nomainwindow) {
		main_form = create_main_form();

		sscanf(Config.get("placement", "100 100 800 415").c_str(), "%d%d%d%d", &x, &y, &w, &h);
		if(*xfgeom) {
			parse_geometry(xfgeom, &x, &y, &w, &h);
			fl_set_initial_placement(main_form, x, y, w, h);
		} else {
			if(Config.getInt("wplace", 1))
				fl_set_initial_placement(main_form, x, y, w, h);
			else
				fl_set_form_size(main_form, w, h);
		}

		if(Config.getInt("starticon", 0))
			xficonic = 1;

		fl_set_form_minsize(main_form, 600, 300);
		fl_set_form_icon(main_form, iconPix_noMail, iconPix_noMail_sh);
		fl_set_atclose(main_close, NULL);
		fl_show_form(main_form,
					 xficonic ? FL_PLACE_ICONIC | FL_FREE_SIZE :
					 FL_FREE_SIZE, FL_FULLBORDER, "XFMail");

		xofft = main_form->x - x;
		yofft = main_form->y - y;

		fl_deactivate_form(main_form);
		set_cursor(main_form, XC_watch);

		if(Config.getInt("startlog", 0))
			log_win();
		else
			fl_set_menu_item_mode(menu_misc, 8, FL_PUP_BOX);

		sprintf(menu, "Send%%F%%t|%s", SEND_MENU);
		spup = fl_defpup(main_form->window, menu, send_pup_cb);

		sprintf(menu, "Message%%F%%t|%s|Send%%m", MESG_MENU);
		mpup = fl_defpup(main_form->window, menu, mesg_pup_cb, spup);

		sprintf(menu, "Folder%%F%%t|%s", FOLD_MENU);
		fpup = fl_defpup(main_form->window, menu, fold_pup_cb);

		fl_setpup_shadow(mpup, 0);
		fl_setpup_shadow(spup, 0);
		fl_setpup_shadow(fpup, 0);
		fl_setpup_softedge(mpup, 0);
		fl_setpup_softedge(spup, 0);
		fl_setpup_softedge(fpup, 0);
	}

	if(cnfdir == 1)
		display_msg(MSG_MSG, "init", "Directory %s has been created",
					configdir);
	else if(cnfdir == 2) {
		snprintf(from, sizeof(from), "%s/.xfbook", Config.get("addrdir", homedir).c_str());
		snprintf(buf, sizeof(buf), "%s/.xfbook", configdir);
		do_move(from, buf);

		snprintf(buf, sizeof(buf), "mv %s/.xfbook.* %s/", Config.get("addrdir", homedir).c_str(), configdir); system(buf);

		display_msg(MSG_MSG, "init",
					"Directory %s has been created\nand XFMail moved all configuration files into it",
					configdir);
	}

	snprintf(sender_name, sizeof(sender_name), "%s@%s", user_n,
			 getmyhostname());

	/* running at the first time */
	if(!Config.exist("from")) {
		readonly = 0;
		if(strlen(gecos) > 1)
			snprintf(from, sizeof(from), "%s <%s@%s>", gecos, user_n,
					 getmyhostname());
		else
			snprintf(from, sizeof(from), "%s@%s", user_n, getmyhostname());

		xfm_config_new(1);  /* misc_conf() */

		if(!Config.exist("spool"))
			xfm_config_new(5);  /* inc_conf()  */

		if(!Config.exist("smtphost"))
			xfm_config_new(4);  /* smtp_conf() */

		Config.set("xfversion", VERSION);
		//Config.save(0);
	} else {
		struct _mail_addr *ma;

		if(((ma = get_address(Config.get("from", "").c_str(), ADDR_GET_FIRST)) == NULL)
		  || ((p = strchr(ma->addr, '@')) == NULL)
		  || (strchr(p, '.') == NULL)) {
			display_msg(MSG_WARN, "Your E-Mail address (From field)",
						"is invalid, please fix it");
			xfm_config_new(1);
		}

		if(ma)
			discard_address(ma);
	}

	logging = Config.getInt("logging", logging);
	msg_form_init();

	display_msg(MSG_LOG, "startup", "Opening all folders");

	sort_type =
	Config.getInt("sort", BY_SNT_TIME | MSG_DESCEND | MSG_THREAD);
	folder_sort = Config.getInt("fsort", BY_NAME | MSG_ASCEND);
	snprintf(maildir, sizeof(maildir), "%s/Mail", homedir);
	my_deactivate();
	supress_questions = 1;
	if(open_all_folders(const_cast<char *>(Config.get("maildir", maildir).c_str()), xfcompose) == -1) {
		display_msg(MSG_FATAL, "init", "initialzation failed");
		exit(1);
	}
	supress_questions = 0;
	my_activate();

	display_msg(MSG_LOG, "startup", "Loading folder configuration");
	if(load_folders_conf(NULL) == -1) {
		display_msg(MSG_FATAL, "init",
					"Failed to load folder configuration");
		exit(1);
	}

	display_msg(MSG_LOG, "startup", "Cleaning temp folders");
	ftemp->empty(ftemp);
	fmbox->empty(fmbox);

	display_msg(MSG_LOG, "startup", "Initializing cache");
	init_cache();

	display_msg(MSG_LOG, "startup", "Loading rules database");
	if(load_rules() == -1)
		display_msg(MSG_WARN, "init", "Failed to load rules");

	display_msg(MSG_LOG, "startup", "Loading default address book");
	if(!load_addressbooks())
		display_msg(MSG_WARN, "init", "Failed to load address book");

	display_msg(MSG_LOG, "startup", "Loading signatures");
	load_signatures();

	display_msg(MSG_LOG, "startup", "Loading mailcap");
	load_mailcap();

	display_msg(MSG_LOG, "startup", "Loading keymap");
	load_keymap();

	display_msg(MSG_LOG, "startup", "Loading accounts");
	load_sources();
	load_smtp_accounts();

	if(!Config.getInt("nntpstorpwd", 0))
		Config.setFlags("nntpasswd", DONT_STORE | CF_UNSECURE);
	else
		Config.setFlags("nntpasswd", CF_UNSECURE);
	Config.setFlags("placement", CF_NOTCHANGED);
	Config.setFlags("msgformsize", CF_NOTCHANGED);
	Config.setFlags("sfolder", CF_NOTCHANGED);
	switch(startup) {
		case STARTUP_NORMAL:
			show_msg[STAT_LEN] = Config.getInt("statlen", 2);
			show_msg[DATE_LEN] = Config.getInt("datelen", 13);
			show_msg[SIZE_LEN] = Config.getInt("sizelen", 5);
			show_msg[FROM_LEN] = Config.getInt("fromlen", 18);
			show_msg[SUBJ_LEN] = Config.getInt("subjlen", 100);
			show_msg[UID_LEN] = Config.getInt("uidlen", 0);
			show_fld[FOLD_LEN] = Config.getInt("foldlen", 11);
			show_fld[FNUM_LEN] = Config.getInt("fnumlen", 4);
			show_fld[FUNR_LEN] = Config.getInt("funrlen", 4);
			sscanf(Config.get("msgcolors", "").c_str(), "%d%d%d%d",
				   &color_msg[MSG_CURR_CLR], &color_msg[MSG_UNREAD_CLR],
				   &color_msg[MSG_MARK_CLR], &color_msg[MSG_NORMAL_CLR]);

			sscanf(Config.get("fldcolors", "").c_str(),
				   "%d%d%d%d%d%d%d%d", &color_fld[FLD_DUMMY_CLR],
				   &color_fld[FLD_SEARCH_CLR], &color_fld[FLD_MARK_CLR],
				   &color_fld[FLD_RECENT_CLR], &color_fld[FLD_SYSTEM_CLR],
				   &color_fld[FLD_IMAP_CLR], &color_fld[FLD_CURR_CLR],
				   &color_fld[FLD_NORMAL_CLR]);

			my_deactivate();

			if(!(current_folder = get_folder_by_name(const_cast<char *>(Config.get("sfolder", INBOX).c_str())))) 
                current_folder = inbox;

			current_folder->open(current_folder, 0);
			mark_to_us(current_folder);
			set_current_message(current_folder->messages, 1);
			offline = Config.getInt("smtpoffl", 0);
			fl_set_timer(inc_timer, Config.getInt("inctime", 180));
			fl_set_timer(send_timer, Config.getInt("sendtime", 0));
			fl_set_timer(trash_timer,
						 Config.getInt("trashtime", 0) * 60);

			for(pi = retrieve_srcs.begin(); pi != retrieve_srcs.end(); pi++) {
				if(pi->type != RSRC_IMAP)
					continue;
				imap = (struct _imap_src *) pi->spec;
				if(imap->flags & ISRC_AUTOCON) {
					imap_init(imap);
					redraw_folders();
				}
			}
			set_menu_imap();

			supress_errors = 2;

			if(Config.getInt("inconstart", 0))
				havemail = (get_new_mail(0, 1) > 0);

			supress_errors = 0;

			set_cursor(main_form, 0);
			fl_set_object_prehandler(b_messages, preemptive_handler);
			fl_set_object_posthandler(b_messages, msg_posthandler);
			fl_set_object_posthandler(b_folders, fld_posthandler);

			my_activate();
			redraw_folders();
			break;

		case STARTUP_COMPOSE:
			current_folder = outbox;
			current_folder->open(current_folder, 0);
			if((current_message = create_message(outbox)) == NULL)
				clean_exit(0);

			if(*xfmsg) {
				if(xfwithhdr) {
					if(set_message_file(current_message, xfmsg) == -1)
						clean_exit(0);
				} else {
					if(set_message_text(current_message, xfmsg) == -1)
						clean_exit(0);
				}
			}

			while(argc-- > 1) {
				if((addr = get_address(argv[argc], ADDR_GET_FIRST)) == NULL)
					continue;
				addr->next_addr = current_message->header->To;
				current_message->header->To = addr;
			}
			current_message->header->To = expand_addr_list(current_message,
														   current_message->
														   header->To);

			if(*xfsubj) {
				if(current_message->header->Subject)
					free(current_message->header->Subject);
				current_message->header->Subject = strdup(xfsubj);
			}

			offline = 0;
			edit_msg(current_message);
			break;
	}

	signal(SIGINT, clean_exit);
	signal(SIGTERM, clean_exit);
	fl_set_idle_callback(idle_cb, NULL);


	initdone = 1;
	display_msg(MSG_STAT, NULL, "Ready");
	display_msg(MSG_LOG, "startup", "Done");
	update_title();
	set_main_icon(havemail, "XFMail");

	TipOfTheDay();

	while(1)
		fl_do_forms();

	clean_exit(0);
}
