/* $Id: inc.cpp,v 1.28 2004/01/02 04:05:36 fesnel Exp $ */
/*******************************************************************************
 *   This program is part of the XFMail email client.                          *
 *                                                                             *
 *   Copyright : (C) 1995-1998 Gennady B. Sorokopud (gena@NetVision.net.il)    *
 *               (C) 1995 Ugen. J. S. Antsilevich (ugen@latte.worldbank.org)   *
 *               (C) 1998-2004 by the Archimedes Project                       *
 *                   http://sourceforge.net/projects/archimedes                *
 *                                                                             *
 *             --------------------------------------------                    *
 *                                                                             *
 *   This program is free software; you can redistribute it and/or modify      *
 *   it under the terms of the GNU General Public License as published by      *
 *   the Free Software Foundation; either version 2 of the License, or         *
 *   (at your option) any later version.                                       *
 *                                                                             *
 *   This program is distributed in the hope that it will be useful,           *
 *   but WITHOUT ANY WARRANTY, without even the implied warranty of            *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             *
 *   GNU General Public License for more details.                              *
 *                                                                             *
 *   You should have received a copy of the GNU General Public License         *
 *   along with this program; if not, write to the Free Software               *
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston MA 02111-1307, USA.  *
 *                                                                             *
 *   Additional Permission granted:                                            *
 *                                                                             *
 *   This program is designed to use the XForms library, so we consider        *
 *   permission to link to that non-GPL-compatible library is implicit.        *
 *   However, in case this is not considered so, we explicitly state:          *
 *                                                                             *
 *   "As a special exception, the Archimedes Project, with the permission      *
 *    of all earlier copyright holders, formally gives permission to link      *
 *    this program with the XForms library, and distribute the resulting       *
 *    executable without the source code for XForms in the source              *
 *    distribution".                                                           *
 *                                                                             *
 ******************************************************************************/


#include <glib.h>

#include <fmail.h>
#include <umail.h>
#include <choose_folder.h>
#include <cfgfile.h>
#include "configform.h"

extern cfgfile Config;

static FD_config_receive *inc_obj;
static FD_config_timers *timers_obj;
static FD_acc_spool *spool_obj;
static int spoolready = 0;
static int ready=0;

/* list of sources to retrieve mail from */
list<struct _retrieve_src> retrieve_srcs;

void spool_acc(struct _retrieve_src *source);
void pop_acc(struct _retrieve_src *source);
void imap_acc(struct _retrieve_src *source);
char *get_src_line(const char *srcname);
struct _retrieve_src *get_selected_source();
void display_sources();
void init_retrieve_source(struct _retrieve_src *source);
void destroy_retrieve_source(struct _retrieve_src *source);

/* list of smtp_accounts to send mail to */
struct _smtp_account smtp_accounts[MAX_SMTP_ACCOUNTS];

void smtp_acc(struct _smtp_account *smtp);
char *get_smtp_acct_line(int smtp_acct);
void display_smtp_accts();
static FD_smtp_add *smtp_obj;


void Inc_Esd_Call(FL_OBJECT * obj, long param) {
#ifdef USE_ESOUND
	fl_deactivate_object(inc_obj->Inc_Play);
	fl_deactivate_object(inc_obj->Inc_Command);
	fl_activate_object(inc_obj->Inc_EsdHost);
	fl_set_focus_object(inc_obj->config_receive, inc_obj->Inc_EsdHost);
	Config.set("use_esd",1);
#else
	fl_show_alert("ESD Not Supported",
				  "This executable was not compiled with ESD support",
				  "Please download the source and recompile with the\n--with-esd-sound option in configuring.",
				  1);
	fl_set_button(inc_obj->Inc_Esd, 0);
	fl_set_button(inc_obj->Inc_Beep, 1);
#endif
}

void Inc_NSound_Call(FL_OBJECT * obj, long param) {
	fl_deactivate_object(inc_obj->Inc_Play);
	fl_deactivate_object(inc_obj->Inc_Command);
	fl_deactivate_object(inc_obj->Inc_EsdHost);
}

void Inc_Beep_Call(FL_OBJECT * obj, long param) {
	fl_deactivate_object(inc_obj->Inc_Play);
	fl_deactivate_object(inc_obj->Inc_Command);
	fl_deactivate_object(inc_obj->Inc_EsdHost);
}

void Inc_SFile_Call(FL_OBJECT * obj, long param) {
	fl_deactivate_object(inc_obj->Inc_Command);
	fl_deactivate_object(inc_obj->Inc_EsdHost);
	fl_activate_object(inc_obj->Inc_Play);
	fl_set_focus_object(inc_obj->config_receive, inc_obj->Inc_Play);
}

void Inc_SCommand_Call(FL_OBJECT * obj, long param) {
	fl_deactivate_object(inc_obj->Inc_Play);
	fl_deactivate_object(inc_obj->Inc_EsdHost);
	fl_activate_object(inc_obj->Inc_Command);
	fl_set_focus_object(inc_obj->config_receive, inc_obj->Inc_Command);
}

void Inc_Play_Call(FL_OBJECT * obj, long param) {
	play_sound((char *) fl_get_input(obj), 100);
}

void Inc_Start_Call(FL_OBJECT * obj, long param) {
}

void Inc_GPasswd_Call(FL_OBJECT * obj, long param) {
#ifdef USE_GPASSWD
	if(fl_get_button(inc_obj->Inc_GPasswd)) {
		fl_show_alert("Now using strong encryption (with a passphrase)",
		    "to store email account passwords for which",
		    "the \"store password\" option is selected.", 1);
		Config.set("use_gpasswd", 1);
		set_passphrase();
	} else {
		fl_show_alert("No longer Using global strong password encryption",
		    "Any stored passwords will not be securely encrypted.",
		    "with a passphrase ", 1);
		Config.set("use_gpasswd", 0);
	}
#else
	fl_show_alert("Encryption not supported",
	    "This executable was not compiled with encryption support",
	    "Please download the source and recompile with the\n--enable-gpasswd option in configuring.",
				  1);
	fl_set_button(inc_obj->Inc_GPasswd, 0);
#endif
}

void Inc_Lock_Call(FL_OBJECT * obj, long param) {
	if(!fl_get_button(inc_obj->Inc_Dotlock) &&
	   !fl_get_button(inc_obj->Inc_Kernelock))
		fl_show_alert("WARNING, no locking method selected!",
					  "Accessing folder without locking",
					  "can lead to folder corruption and data loss!!",
					  1);
}

struct _retrieve_src *get_selected_source() {
	int sline;
	list<struct _retrieve_src>::iterator p;

	if((sline = fl_get_browser(inc_obj->Inc_Sources)) < 1)
		return NULL;

	for(p = retrieve_srcs.begin(); p != retrieve_srcs.end(); p++)
		if(--sline == 0)
			return &(*p);

	return NULL;
}

void Inc_Add_Call(FL_OBJECT * obj, long param) {
	int src_pup;
	char *srcname, *cp;
	struct _retrieve_src src;
	list<struct _retrieve_src>::iterator p;

	src_pup =
	fl_defpup(obj->form->window, "Account type%t|Spool|POP|IMAP");

	init_retrieve_source(&src);
	
	switch(fl_dopup(src_pup)) {
		case 1:
			src.type = RSRC_SPOOL;
			break;

		case 2:
			src.type = RSRC_POP;
			break;

		case 3:
			src.type = RSRC_IMAP;
			break;

		default:
			fl_freepup(src_pup);
			return;
			break;
	}
	fl_freepup(src_pup);

	srcname = (char *) fl_show_input("Account name:", "");
	if(!srcname || !*srcname)
		return;

	if(strlen(srcname) >= sizeof(src.name)) {
		display_msg(MSG_WARN, "add account",
					"account name too long (should be 1-%d characters)",
					sizeof(src.name) - 1);
		return;
	}

	for(cp = srcname; *cp; cp++) {
		if(!isalpha(*cp) && !isdigit(*cp) && *cp != '_'
			&& (cp == srcname || (*cp != '-' && *cp != '.'))) {
			display_msg(MSG_WARN, "add account",
				"Invalid character in account name (only \"a-zA-Z0-9_-.\" are allowed)");
			return;
		}
	}

	for(p = retrieve_srcs.begin(); p != retrieve_srcs.end(); p++) {
		if(!strcasecmp(srcname, (*p).name)) {
			display_msg(MSG_WARN, "add account",
						"account %s already exists", srcname);
			return;
		}
	}

	strcpy(src.name, srcname);
	src.flags = 0;
	src.spec = NULL;
	switch(src.type) {
		case RSRC_SPOOL:
			spool_source(&src);
			break;

		case RSRC_POP:
			pop_source(&src);
			break;

		case RSRC_IMAP:
			imap_source(&src);
			break;
	}

	retrieve_srcs.push_back(src);
	/* Add IMAP source to IMAP menu */
	if (src.type == RSRC_IMAP)
		set_menu_imap();

	fl_addto_browser(inc_obj->Inc_Sources, get_src_line(src.name));
	fl_select_browser_line(inc_obj->Inc_Sources,
	    fl_get_browser_maxline(inc_obj->Inc_Sources));
	Inc_Edit_Call(obj, param);

	return;
}

void Inc_Delete_Call(FL_OBJECT * obj, long param) {
	struct _imap_src *imap;
	struct _retrieve_src *src = get_selected_source();
	list<struct _retrieve_src>::iterator p;
	bool isimap;

	if(src == NULL)
		return;

	isimap = src->type == RSRC_IMAP;
	if(isimap) {
		imap = (struct _imap_src *) src->spec;
		if(imap_isconnected(imap)) {
			display_msg(MSG_WARN, "delete account",
						"IMAP connection to %s is established\ncan not delete account",
						imap->hostname);
			return;
		}
	}

	destroy_retrieve_source(src);
	for (p = retrieve_srcs.begin(); p != retrieve_srcs.end(); p++)
		if (src == &(*p)) {
			retrieve_srcs.erase(p);
			break;
		}
	display_sources();
	if(isimap)
		set_menu_imap();

	return;
}

void Inc_Edit_Call(FL_OBJECT * obj, long param) {
	struct _retrieve_src *src = get_selected_source();
	struct _imap_src *imap;

	if(src == NULL)
		return;

	fl_deactivate_object(inc_obj->Inc_Add);
	fl_deactivate_object(inc_obj->Inc_Delete);
	fl_deactivate_object(inc_obj->Inc_Edit);
	switch(src->type) {
		case RSRC_SPOOL:
			spool_acc(src);
			break;

		case RSRC_POP:
			pop_acc(src);
			break;

		case RSRC_IMAP:
			imap = (struct _imap_src *) src->spec;
			if(imap_isconnected(imap)) {
				display_msg(MSG_WARN, "edit account",
							"IMAP connection to %s is established\ncan not edit account",
							imap->hostname);
				break;
			}
			imap_acc(src);
			break;
	}
	fl_activate_object(inc_obj->Inc_Add);
	fl_activate_object(inc_obj->Inc_Delete);
	fl_activate_object(inc_obj->Inc_Edit);

	fl_replace_browser_line(inc_obj->Inc_Sources,
	    fl_get_browser(inc_obj->Inc_Sources), get_src_line(src->name));
	return;
}

void Inc_Src_Call(FL_OBJECT * obj, long param) {
	struct _retrieve_src *src = get_selected_source();

	if(src == NULL)
		return;

	if(fl_mouse_button() == FL_MIDDLE_MOUSE) {
		Inc_Edit_Call(obj, param);
		return;
	}

	fl_set_button(inc_obj->Inc_Disabled,
	    (src->flags & RSRC_DISABLED) ? 1 : 0);
	fl_set_button(inc_obj->Inc_Markread,
	    (src->flags & RSRC_MARKREAD) ? 1 : 0);
	fl_set_button(inc_obj->Inc_DNotify,
	    (src->flags & RSRC_NONOTIFY) ? 1 : 0);
	fl_set_button(inc_obj->Inc_SAddr,
	    (src->flags & RSRC_SAVEADDR) ? 1 : 0);
	fl_set_button(inc_obj->Inc_Notimer,
	    (src->flags & RSRC_NOTIMER) ? 1 : 0);
	fl_set_button(inc_obj->Inc_Download,
	    (src->flags & RSRC_DOWNLOAD) ? 1 : 0);

	return;
}

void Inc_Disabled_Call(FL_OBJECT * obj, long param) {
	struct _retrieve_src *src = get_selected_source();

	if(src == NULL)
		return;

	if(fl_get_button(obj))
		src->flags |= RSRC_DISABLED;
	else
		src->flags &= ~RSRC_DISABLED;
}

void Inc_Markread_Call(FL_OBJECT * obj, long param) {
	struct _retrieve_src *src = get_selected_source();

	if(src == NULL)
		return;

	if(fl_get_button(obj))
		src->flags |= RSRC_MARKREAD;
	else
		src->flags &= ~RSRC_MARKREAD;
}

void Inc_DNotify_Call(FL_OBJECT * obj, long param) {
	struct _retrieve_src *src = get_selected_source();

	if(src == NULL)
		return;

	if(fl_get_button(obj))
		src->flags |= RSRC_NONOTIFY;
	else
		src->flags &= ~RSRC_NONOTIFY;
}

void Inc_SAddr_Call(FL_OBJECT * obj, long param) {
	struct _retrieve_src *src = get_selected_source();

	if(src == NULL)
		return;

	if(fl_get_button(obj))
		src->flags |= RSRC_SAVEADDR;
	else
		src->flags &= ~RSRC_SAVEADDR;
}

void Inc_Notimer_Call(FL_OBJECT * obj, long param) {
	struct _retrieve_src *src = get_selected_source();

	if(src == NULL)
		return;

	if(fl_get_button(obj))
		src->flags |= RSRC_NOTIMER;
	else
		src->flags &= ~RSRC_NOTIMER;
}

void Inc_Download_Call(FL_OBJECT * obj, long param) {
	struct _retrieve_src *src = get_selected_source();

	if(src == NULL)
		return;

	if(fl_get_button(obj))
		src->flags |= RSRC_DOWNLOAD;
	else
		src->flags &= ~RSRC_DOWNLOAD;
}

char *get_src_line(const char *srcname) {
	static char srcline[96];
	struct _spool_src *spool;
	struct _pop_src *pop;
	struct _imap_src *imap;
	list<struct _retrieve_src>::iterator p;
	struct _retrieve_src *src;

	for (p = retrieve_srcs.begin(); p != retrieve_srcs.end(); p++)
		if (strcasecmp(srcname, p->name) == 0) {
			src = &(*p);
			break;
		}
	if (src == NULL)
		return NULL;
	
	switch(src->type) {
		case RSRC_SPOOL:
			spool = (struct _spool_src *) src->spec;
			snprintf(srcline, sizeof(srcline), "%s [%s]",
					 src->name, spool->path);
			break;

		case RSRC_POP:
			pop = (struct _pop_src *) src->spec;
			snprintf(srcline, sizeof(srcline), "%s [%s/%s %s]",
					 src->name, pop->hostname, pop->service,
					 pop->username);
			break;

		case RSRC_IMAP:
			imap = (struct _imap_src *) src->spec;
			snprintf(srcline, sizeof(srcline), "%s [%s/%s %s]",
					 src->name, imap->hostname, imap->service,
					 imap->username);
			break;

		default:
			strcpy(srcline, src->name);
			break;
	}
	return srcline;
}

void display_sources() {
	int bset = 0;
	list<struct _retrieve_src>::iterator p;

	fl_freeze_form(inc_obj->config_receive);
	fl_set_button(inc_obj->Inc_Disabled, 0);
	fl_set_button(inc_obj->Inc_Markread, 0);
	fl_set_button(inc_obj->Inc_DNotify, 0);
	fl_set_button(inc_obj->Inc_SAddr, 0);
	fl_set_button(inc_obj->Inc_Notimer, 0);
	fl_set_button(inc_obj->Inc_Download, 0);
	fl_clear_browser(inc_obj->Inc_Sources);

	for(p = retrieve_srcs.begin(); p != retrieve_srcs.end(); p++) {

		fl_add_browser_line(inc_obj->Inc_Sources,
		    get_src_line(p->name));
		if(!bset) {
			fl_set_button(inc_obj->Inc_Disabled,
			    (p->flags & RSRC_DISABLED) ? 1 : 0);
			fl_set_button(inc_obj->Inc_Markread,
			    (p->flags & RSRC_MARKREAD) ? 1 : 0);
			fl_set_button(inc_obj->Inc_DNotify,
			    (p->flags & RSRC_NONOTIFY) ? 1 : 0);
			fl_set_button(inc_obj->Inc_SAddr,
			    (p->flags & RSRC_SAVEADDR) ? 1 : 0);
			fl_set_button(inc_obj->Inc_Notimer,
			    (p->flags & RSRC_NOTIMER) ? 1 : 0);
			fl_set_button(inc_obj->Inc_Download,
			    (p->flags & RSRC_DOWNLOAD) ? 1 : 0);
			bset = 1;
		}
	}


	fl_select_browser_line(inc_obj->Inc_Sources, 1);
	fl_unfreeze_form(inc_obj->config_receive);

	return;
}

void inc_conf(int set_default, FD_config_receive * form) {

	inc_obj = form;
	display_sources();

	fl_set_button(inc_obj->Inc_Start, Config.getIntDefault("inconstart", 0, set_default));
	fl_set_button(inc_obj->Inc_Show, Config.getIntDefault("incresults", 1, set_default));
	if(locking & MBOX_DOT_LOCK)
		fl_set_button(inc_obj->Inc_Dotlock, 1);
	else
		fl_set_button(inc_obj->Inc_Dotlock, 0);
	if(locking & MBOX_KERNEL_LOCK)
		fl_set_button(inc_obj->Inc_Kernelock, 1);
	else
		fl_set_button(inc_obj->Inc_Kernelock, 0);

	if(Config.getInt("use_gpasswd",0) != 0)
		fl_set_button(inc_obj->Inc_GPasswd, 1);
	else
		fl_set_button(inc_obj->Inc_GPasswd, 0);

	switch(Config.getIntDefault("beep", 1, set_default)) {
		case 0:
			fl_set_button(inc_obj->Inc_NSound, 1);
			fl_set_button(inc_obj->Inc_Beep, 0);
			fl_set_button(inc_obj->Inc_SFile, 0);
			fl_set_button(inc_obj->Inc_SCommand, 0);
			fl_set_button(inc_obj->Inc_Esd, 0);
			fl_deactivate_object(inc_obj->Inc_Play);
			fl_deactivate_object(inc_obj->Inc_Command);
			fl_deactivate_object(inc_obj->Inc_EsdHost);
			break;

		case 1:
			fl_set_button(inc_obj->Inc_NSound, 0);
			fl_set_button(inc_obj->Inc_Beep, 1);
			fl_set_button(inc_obj->Inc_SFile, 0);
			fl_set_button(inc_obj->Inc_SCommand, 0);
			fl_set_button(inc_obj->Inc_Esd, 0);
			fl_deactivate_object(inc_obj->Inc_Play);
			fl_deactivate_object(inc_obj->Inc_Command);
			fl_deactivate_object(inc_obj->Inc_EsdHost);
			break;

		case 2:
			fl_set_button(inc_obj->Inc_NSound, 0);
			fl_set_button(inc_obj->Inc_Beep, 0);
			fl_set_button(inc_obj->Inc_SFile, 1);
			fl_set_button(inc_obj->Inc_SCommand, 0);
			fl_set_button(inc_obj->Inc_Esd, 0);
			fl_activate_object(inc_obj->Inc_Play);
			fl_deactivate_object(inc_obj->Inc_Command);
			fl_deactivate_object(inc_obj->Inc_EsdHost);
			fl_set_input(inc_obj->Inc_Play,
						 Config.get("play", "", set_default).c_str());
		   	break;

		case 3:
			fl_set_button(inc_obj->Inc_NSound, 0);
			fl_set_button(inc_obj->Inc_Beep, 0);
			fl_set_button(inc_obj->Inc_SFile, 0);
			fl_set_button(inc_obj->Inc_SCommand, 1);
			fl_set_button(inc_obj->Inc_Esd, 0);
			fl_deactivate_object(inc_obj->Inc_Play);
			fl_activate_object(inc_obj->Inc_Command);
			fl_deactivate_object(inc_obj->Inc_EsdHost);
			fl_set_input(inc_obj->Inc_Command,
						 Config.get("play", "", set_default).c_str()); 
			break;

		case 4:
			fl_set_button(inc_obj->Inc_NSound, 0);
			fl_set_button(inc_obj->Inc_Beep, 0);
			fl_set_button(inc_obj->Inc_SFile, 0);
			fl_set_button(inc_obj->Inc_SCommand, 0);
			fl_set_button(inc_obj->Inc_Esd, 1);
			fl_deactivate_object(inc_obj->Inc_Play);
			fl_deactivate_object(inc_obj->Inc_Command);
			fl_activate_object(inc_obj->Inc_EsdHost);
			fl_set_input(inc_obj->Inc_EsdHost,
						 Config.get("esd_host", "localhost", set_default).c_str()); 
			break;
		default:
			fl_set_button(inc_obj->Inc_NSound, 1);
			fl_set_button(inc_obj->Inc_Beep, 0);
			fl_set_button(inc_obj->Inc_SFile, 0);
			fl_set_button(inc_obj->Inc_SCommand, 0);
			fl_deactivate_object(inc_obj->Inc_Play);
			fl_deactivate_object(inc_obj->Inc_Command);
			fl_deactivate_object(inc_obj->Inc_EsdHost);
			break;
	}
}

void Inc_Icon_Call(FL_OBJECT * obj, long param) {
}

void Inc_Count_Call(FL_OBJECT * obj, long param) {
}

void handle_inc_input(FD_config_receive * form) {

	inc_obj = form;

	save_sources(NULL);
	save_smtp_accounts(NULL); /* global password encryption may have changed */

	Config.set("inconstart", fl_get_button(inc_obj->Inc_Start));
	Config.set("incresults", fl_get_button(inc_obj->Inc_Show));

	locking = 0;

	if(fl_get_button(inc_obj->Inc_Kernelock))
		locking |= MBOX_KERNEL_LOCK;
	if(fl_get_button(inc_obj->Inc_Dotlock))
		locking |= MBOX_DOT_LOCK;
	Config.set("spoolock", locking);


	if(fl_get_button(inc_obj->Inc_GPasswd))
		Config.set("use_gpasswd", 1);

	if(fl_get_button(inc_obj->Inc_NSound))
		Config.set("beep", 0);
	else if(fl_get_button(inc_obj->Inc_Beep))
		Config.set("beep", 1);
	else if(fl_get_button(inc_obj->Inc_SFile)) {
		Config.set("beep", 2);
		Config.set("play", (char *) fl_get_input(inc_obj-> Inc_Play));
	} else if(fl_get_button(inc_obj->Inc_SCommand)) {
		Config.set("beep", 3);
		Config.set("play", (char *) fl_get_input(inc_obj-> Inc_Command));
	} else if(fl_get_button(inc_obj->Inc_Esd)) {
		Config.set("beep", 4);
		Config.set("use_esd", 1);
		Config.set("esd_host", (char *) fl_get_input(inc_obj-> Inc_EsdHost));
	} else Config.set("beep", 0);

	return;
}

void timers_conf(int set_default, FD_config_timers * form) {
	timers_obj = form;

	fl_set_counter_bounds(timers_obj->Inc_Count, 0, 120);
	fl_set_counter_precision(timers_obj->Inc_Count, 2);
	fl_set_counter_step(timers_obj->Inc_Count, 0.25, 5);
	fl_set_counter_value(timers_obj->Inc_Count,
						 (double) ((double) Config.getIntDefault("inctime", 
																 180,
																 set_default) /
								   (double) 60));
	fl_set_counter_bounds(timers_obj->Inc_Send, 0, 60);
	fl_set_counter_precision(timers_obj->Inc_Send, 1);
	fl_set_counter_step(timers_obj->Inc_Send, 0.5, 5);
	fl_set_counter_value(timers_obj->Inc_Send,
						 (double) ((double) Config.getIntDefault("sendtime", 0,
												 set_default) /
								   (double) 60));
	fl_set_counter_bounds(timers_obj->Timer_Trash, 0, 48);
	fl_set_counter_precision(timers_obj->Timer_Trash, 1);
	fl_set_counter_step(timers_obj->Timer_Trash, 0.5, 5);
	fl_set_counter_value(timers_obj->Timer_Trash,
						 (double) ((double) Config.getIntDefault("trashtime", 0,
												 set_default) /
								   (double) 60));
	fl_set_counter_bounds(timers_obj->Timer_Autosave, 0, 60);
	fl_set_counter_precision(timers_obj->Timer_Autosave, 1);
	fl_set_counter_step(timers_obj->Timer_Autosave, 0.5, 5);
	fl_set_counter_value(timers_obj->Timer_Autosave,
						 (double) ((double) Config.getIntDefault("asavetime",
												 180,
												 set_default) /
								   (double) 60));
	fl_set_counter_bounds(timers_obj->Timer_IMAP, 0, 120);
	fl_set_counter_precision(timers_obj->Timer_IMAP, 2);
	fl_set_counter_step(timers_obj->Timer_IMAP, 0.25, 5);
	fl_set_counter_value(timers_obj->Timer_IMAP,
						 (double) ((double) Config.getIntDefault("imaptime",
												 600,
												 set_default) /
								   (double) 60));
	fl_set_counter_bounds(timers_obj->Timer_PGP, 0, PGP_MAX_TIMER);
	fl_set_counter_precision(timers_obj->Timer_PGP, 0);
	fl_set_counter_step(timers_obj->Timer_PGP, 1, 5);
	fl_set_counter_value(timers_obj->Timer_PGP,
						 (double) Config.getIntDefault("pgptimer", 120,
													   set_default));
	fl_set_counter_bounds(timers_obj->Timer_Preview, 0, PREVIEW_MAX_TIMER);
	fl_set_counter_precision(timers_obj->Timer_Preview, 0);
	fl_set_counter_step(timers_obj->Timer_Preview, 1, 5);
	fl_set_counter_value(timers_obj->Timer_Preview,
						 (double) Config.getIntDefault("previewtime", 0,
													   set_default));
	fl_set_button(timers_obj->Inc_Icon,
				  Config.getIntDefault("incwhenicon", 1, set_default));
}

void handle_timers_input(FD_config_timers * form) {
	int i;
	timers_obj = form;
	Config.set("inctime", (int) (fl_get_counter_value(timers_obj->Inc_Count) *
						 60));
	Config.set("sendtime",
				  (int) (fl_get_counter_value(timers_obj->Inc_Send) *
						 60));
	Config.set("trashtime",
				  (int) (fl_get_counter_value(timers_obj->Timer_Trash)
						 * 60));
	Config.set("asavetime",
				  (int) (fl_get_counter_value(timers_obj->Timer_Autosave) *
						 60));
	Config.set("imaptime",
				  (int) (fl_get_counter_value(timers_obj->Timer_IMAP) *
						 60));
	Config.set("pgptimer",
				  (int) fl_get_counter_value(timers_obj->Timer_PGP));
	Config.set("previewtime",
				  (int) fl_get_counter_value(timers_obj->
											 Timer_Preview));
	fl_set_timer(inc_timer, Config.getInt("inctime", 180));
	i = Config.getInt("sendtime", 0);
	if(i)
		i++;
	fl_set_timer(send_timer, i);

	i = Config.getInt("trashtime", 0);
	if(i)
		i += 2;
	fl_set_timer(trash_timer, i);

	if(asave_timer) {
		i = Config.getInt("asavetime", 0);
		if(i)
			i += 3;
		fl_set_timer(asave_timer, i);
	}

	Config.set("incwhenicon", fl_get_button(timers_obj->Inc_Icon));
	return;
}

/* check if name is a source name, and return type */
int search_sources(char * name) {
  int len = strlen(name);
  list<struct _retrieve_src>::iterator p;

  for(p = retrieve_srcs.begin(); p != retrieve_srcs.end(); p++)
	if (strncmp(p->name, name, len) == 0)
	  return p->type;

  return 0x00;
}

int load_sources() {
  FILE *sfd;
  char srcfile[MAXPATHLEN], buf[255];
  int 	loaded = 0;
  struct _retrieve_src src;
  
  snprintf(srcfile, sizeof(srcfile), "%s/.xfmsources", configdir);
  if((sfd = fopen(srcfile, "r")) == NULL) {
	display_msg(MSG_LOG, "load sources",
		"WARNING: no retrieve sources/accounts defined");
	return 0;
  }

  retrieve_srcs.clear();
  while(fgets(buf, sizeof(buf), sfd)) {
	if(*buf != '@')
	  continue;

	init_retrieve_source(&src);
	
	strip_newline(buf);
	if(sscanf(buf, "@ %d%d%31s", &src.flags, &src.type, src.name) != 3) {
	  display_msg(MSG_WARN, "load sources",
		  "Invalid line in %s\nignoring", srcfile);
	  continue;
	}
	src.name[sizeof(src.name) - 1] = '\0';

	switch(src.type) {
	default:
	case RSRC_SPOOL:
	  spool_source(&src);
	  break;
	  
	case RSRC_POP:
	  pop_source(&src);
	  break;
	  
	case RSRC_IMAP:
	  imap_source(&src);
	  break;
	}
	
	if((src.load)(&src, sfd) != 0) {
	  display_msg(MSG_WARN, "load sources",
		  "Failed to load source '%s'", src.name);
	  continue;
	}
	
	retrieve_srcs.push_back(src);
	loaded++;
  }
  
  fclose(sfd);
  
  if(loaded == 0)
	display_msg(MSG_LOG, "load sources",
		"WARNING: no retrieve sources/accounts defined");
  
  return loaded;
}







int save_sources(char *tmpf) {
	FILE *sfd;
	char tmpfile[MAXPATHLEN], srcfile[MAXPATHLEN];
	int oflags = 0;
	list<struct _retrieve_src>::iterator p;

	if(readonly)
		return 0;

	if(tmpf)
		snprintf(tmpfile, sizeof(tmpfile), "%s", tmpf);
	else
		snprintf(tmpfile, sizeof(tmpfile), "%s/.xfmsources__sve", configdir);

	snprintf(srcfile, sizeof(srcfile), "%s/.xfmsources", configdir);
	if((sfd = fopen(tmpfile, "w")) == NULL) {
		display_msg(MSG_WARN, "save sources", "Can not open %s", tmpfile);
		return -1;
	}

	for(p = retrieve_srcs.begin(); p != retrieve_srcs.end(); p++) {
		fprintf(sfd, "@ %d %d %s\n", p->flags, p->type, p->name);
		if(tmpf) {
			switch(p->type) {
				case RSRC_POP:
					oflags =
					((struct _pop_src *) p->spec)->flags;
					((struct _pop_src *) p->spec)->flags &=
					~PSRC_STOREPWD;
					break;

				case RSRC_IMAP:
					oflags =
					((struct _imap_src *) p->spec)->flags;
					((struct _imap_src *) p->spec)->flags &=
					~ISRC_STOREPWD;
					break;
			}
		}
		(p->save)(&(*p), sfd);
		if(tmpf) {
			switch(p->type) {
				case RSRC_POP:
					((struct _pop_src *) p->spec)->flags = oflags;
					break;

				case RSRC_IMAP:
					((struct _imap_src *) p->spec)->flags = oflags;
					break;
			}
		}
	}

	fclose(sfd);

	if(tmpf)
		return 0;
	if(rename(tmpfile, srcfile) == -1) {
		display_msg(MSG_WARN, "save sources", "Can not rename %s to\n%s",
					tmpfile, srcfile);
		return -1;
	}
	return 0;
}

void init_retrieve_source(struct _retrieve_src *source)
{

	memset(source->name, '0', sizeof(source->name));
	source->flags = RSRC_DISABLED;
	source->type = 0;
	source->spec = NULL;
	source->retrieve = NULL;
	source->free = NULL;
	source->init = NULL;
	source->load = NULL;
	source->save = NULL;
}

void destroy_retrieve_source(struct _retrieve_src *source)
{

	if (source->free != NULL)
		(source->free)(source);
}

void free_sources() {
	list<struct _retrieve_src>::iterator p;

	for(p = retrieve_srcs.begin(); p != retrieve_srcs.end(); p++)
		destroy_retrieve_source(&(*p));
	retrieve_srcs.clear();
}

int load_smtp_accounts() {
  FILE *sfd;
  char srcfile[MAXPATHLEN], buf[255];
  int loaded = 0;
  int i;

	for (i = 0; i < MAX_SMTP_ACCOUNTS; i++ ) {
	  *smtp_accounts[i].name = '\0';
	  init_smtp_acct(&smtp_accounts[i]);
	}
  
  snprintf(srcfile, sizeof(srcfile), "%s/.xfmsmtp_accts", configdir);
  if((sfd = fopen(srcfile, "r")) == NULL) 
	return 0;
  
  while(fgets(buf, sizeof(buf), sfd)) {
	if(*buf != '@')
	  continue;
	
	strip_newline(buf);
	if(sscanf(buf, "@ %31s",smtp_accounts[loaded].name) != 1) {
	  display_msg(MSG_WARN, "load smtp accounts",
		  "Invalid line in %s\nignoring", srcfile);
	  *smtp_accounts[loaded].name = '\0';
	  continue;
	}
	smtp_accounts[loaded].name[sizeof(smtp_accounts[loaded].name) - 1] = '\0';
	
	if(load_smtp_acct(&smtp_accounts[loaded], sfd) != 0) {
	  display_msg(MSG_WARN, "load smtp accounts",
		  "Failed to load smtp account '%s'",
		  smtp_accounts[loaded].name);
	  *smtp_accounts[loaded].name = '\0';
	  continue;
	}
	
	loaded++;
  }
  fclose(sfd);
  
  return loaded;
}

int save_smtp_accounts(char *tmpf) {
	FILE *sfd;
	char tmpfile[MAXPATHLEN], srcfile[MAXPATHLEN];
	int i;

	if(readonly)
		return 0;

	if(tmpf)
		snprintf(tmpfile, sizeof(tmpfile), "%s", tmpf);
	else
		snprintf(tmpfile, sizeof(tmpfile), "%s/.xfmsmtp_accts__sve", configdir);

	snprintf(srcfile, sizeof(srcfile), "%s/.xfmsmtp_accts", configdir);
	if((sfd = fopen(tmpfile, "w")) == NULL) {
		display_msg(MSG_WARN, "save smtp accounts", "Can not open %s", tmpfile);
		return -1;
	}

	for(i = 0; i < MAX_SMTP_ACCOUNTS; i++) {
		if(*smtp_accounts[i].name == '\0')
			continue;
		fprintf(sfd, "@ %s\n", smtp_accounts[i].name);
	save_smtp_acct(&smtp_accounts[i], sfd);
	}
	fclose(sfd);

	if(tmpf)
		return 0;
	if(rename(tmpfile, srcfile) == -1) {
		display_msg(MSG_WARN, "save smtp accounts", "Can not rename %s to\n%s",
					tmpfile, srcfile);
		return -1;
	}
	return 0;
}

void Spool_Call(FL_OBJECT * obj, long param) {
}

struct _retrieve_src *get_src_by_name(char *name) {
	list<struct _retrieve_src>::iterator p;

	if(!name || !*name)
		return NULL;

	for(p = retrieve_srcs.begin(); p != retrieve_srcs.end(); p++)
		if(!strcasecmp(p->name, name))
			return &(*p);

	return NULL;
}

struct _spool_src *get_spoolsrc_by_name(char *name) {
	struct _retrieve_src *source;

	if(((source = get_src_by_name(name)) == NULL) ||
	   (source->type != RSRC_SPOOL)) return NULL;

	return(struct _spool_src *) source->spec;
}

struct _pop_src *get_popsrc_by_name(char *name) {
	struct _retrieve_src *source;

	if(((source = get_src_by_name(name)) == NULL) ||
	   (source->type != RSRC_POP)) return NULL;

	return(struct _pop_src *) source->spec;
}

struct _imap_src *get_imapsrc_by_name(char *name) {
	struct _retrieve_src *source;

	if(((source = get_src_by_name(name)) == NULL) ||
	   (source->type != RSRC_IMAP)) return NULL;

	return(struct _imap_src *) source->spec;
}

struct _retrieve_src *get_msg_src(struct _mail_msg *msg) {
	struct _head_field *fld;

	if((fld = find_field(msg, SOURCE_FIELD)) == NULL)
		return NULL;

	return get_src_by_name(fld->f_line);
}

struct _spool_src *get_msg_spoolsrc(struct _mail_msg *msg) {
	struct _retrieve_src *source;

	if(((source = get_msg_src(msg)) == NULL) ||
	   (source->type != RSRC_SPOOL)) return NULL;

	return(struct _spool_src *) source->spec;
}

struct _pop_src *get_msg_popsrc(struct _mail_msg *msg) {
	struct _retrieve_src *source;

	if(((source = get_msg_src(msg)) == NULL) ||
	   (source->type != RSRC_POP)) return NULL;

	return(struct _pop_src *) source->spec;
}

struct _imap_src *get_msg_imapsrc(struct _mail_msg *msg) {
	struct _retrieve_src *source;

	if(((source = get_msg_src(msg)) == NULL) ||
	   (source->type != RSRC_IMAP)) return NULL;

	return(struct _imap_src *) source->spec;
}

void spool_acc(struct _retrieve_src *source) {
	struct _spool_src *spool;
	struct _mail_folder *ifold;
	char buf[64];

	spool = (struct _spool_src *) source->spec;
	if(spoolready)
		return;
	spoolready = 1;

	spool_obj = create_form_acc_spool();
	fl_set_input(spool_obj->Spool_Path, spool->path);
	fl_set_button(spool_obj->Spool_Leave,
				  (spool->flags & SSRC_TRUNCATE) ? 0 : 1);
	fl_set_button(spool_obj->Spool_Rewrite,
				  (spool->flags & SSRC_REWRITE) ? 1 : 0);

	fl_show_form(spool_obj->acc_spool, FL_PLACE_CENTER, FL_TRANSIENT,
				 "Spool mailbox");
	spoolenter:
	fl_do_only_forms();

	strcpy(spool->path, fl_get_input(spool_obj->Spool_Path));
	spool->flags = 0;
	if(!fl_get_button(spool_obj->Spool_Leave))
		spool->flags |= SSRC_TRUNCATE;
	if(fl_get_button(spool_obj->Spool_Rewrite))
		spool->flags |= SSRC_REWRITE;

	if((ifold = get_mbox_folder_by_path(spool->path)) == NULL) {
		if((ifold = create_mbox_folder(NULL, spool->path)) == NULL) {
			display_msg(MSG_WARN, "spool", "Can not access %s",
						spool->path);
			goto spoolenter;
		}
	}
	ifold->status |= (FRESCAN | SYSTEM | NOINFR | FNOCLSE);
	ifold->status &= ~FSHORTH;
	if(!(spool->flags & SSRC_REWRITE))
		ifold->status |= FNOMOD;
	else
		ifold->status &= ~FNOMOD;

	if(ifold->sname) {
		snprintf(buf, sizeof(buf), "%s (spool)",
				 get_folder_short_name(ifold));
		free(ifold->sname);
	} else
		sprintf(buf, "spool");
	ifold->sname = strdup(buf);
	if(!ifold->descr)
		ifold->descr = strdup("spool mailbox");
	ifold->open(ifold, FOPEN_NOCACHE);
	sort_folders();
	redraw_fld_win();

	fl_hide_form(spool_obj->acc_spool);
	fl_free_form(spool_obj->acc_spool);
	fl_free(spool_obj);
	spool_obj = NULL;

	spoolready = 0;
	return;
}


/* added XForms GUI stuff for configurable SMTP  accounts */


int get_selected_smtp_acct() {
	int sline, i;

	if((sline = fl_get_browser(smtp_obj->Inc_SMTP_Accts)) < 1)
		return -1;

	for(i = 0; i < MAX_SMTP_ACCOUNTS; i++) {
		if(*smtp_accounts[i].name == '\0')
			continue;

		if(--sline == 0)
			return i;
	}

	return -1;
}


void Inc_SMTP_Acct_Add_Call(FL_OBJECT * obj, long param) {
	int i, k;
	char *acctname, *p;

	for(i = 0; i < MAX_SMTP_ACCOUNTS; i++) {
		if(*smtp_accounts[i].name == '\0')
			break;
	}

	if(i == MAX_SMTP_ACCOUNTS) {
		display_msg(MSG_WARN, "add SMTP account",
					"You can not configure more than %d SMTP accounts",
					MAX_SMTP_ACCOUNTS);
		return;
	}

	acctname = (char *) fl_show_input("SMTP account name:", "");
	if(!acctname || !*acctname)
		return;

	if(strlen(acctname) >= sizeof(smtp_accounts[0].name)) {
		display_msg(MSG_WARN, "add SMTP account",
					"account name too long (should be 1-%d characters)",
					sizeof(smtp_accounts[0].name) - 1);
		return;
	}

	for(p = acctname; *p; p++) {
		if(!isalpha(*p) && !isdigit(*p) && *p != '_'
			&& (p == acctname || (*p != '-' && *p != '.'))) {
			display_msg(MSG_WARN, "add SMTP account",
				"Invalid character in account name (only \"a-zA-Z0-9_-.\" are allowed)");
			return;
		}
	}

	for(k = 0; k < MAX_SMTP_ACCOUNTS; k++) {
		if(!strcasecmp(acctname, smtp_accounts[k].name)) {
			display_msg(MSG_WARN, "add account",
						"account %s already exists", acctname);
			return;
		}
	}

	strcpy(smtp_accounts[i].name, acctname);
	smtp_accounts[i].flags = 0;

	init_smtp_acct(&smtp_accounts[i]);


	fl_addto_browser(smtp_obj->Inc_SMTP_Accts, get_smtp_acct_line(i));
	fl_select_browser_line(smtp_obj->Inc_SMTP_Accts,
						   fl_get_browser_maxline(smtp_obj->Inc_SMTP_Accts));
	Inc_SMTP_Acct_Edit_Call(obj, param);

	return;
}

void Inc_SMTP_Acct_Delete_Call(FL_OBJECT * obj, long param) {
	int i = get_selected_smtp_acct();

	if(i < 0)
		return;

	*smtp_accounts[i].name = '\0';
	display_smtp_accts();

	return;
}

void Inc_SMTP_Acct_Edit_Call(FL_OBJECT *obj, long param) {
	int i = get_selected_smtp_acct();

	if(i < 0)
		return;

	fl_deactivate_object(smtp_obj->Inc_SMTP_Acct_Add);
	fl_deactivate_object(smtp_obj->Inc_SMTP_Acct_Delete);
	fl_deactivate_object(smtp_obj->Inc_SMTP_Acct_Edit);

	smtp_acc(&smtp_accounts[i]);

	fl_activate_object(smtp_obj->Inc_SMTP_Acct_Add);
	fl_activate_object(smtp_obj->Inc_SMTP_Acct_Delete);
	fl_activate_object(smtp_obj->Inc_SMTP_Acct_Edit);

	fl_replace_browser_line(smtp_obj->Inc_SMTP_Accts,
							fl_get_browser(smtp_obj->Inc_SMTP_Accts),
							get_smtp_acct_line(i));
}


void display_smtp_accts() {
	int i, bset = 0;

	fl_freeze_form(smtp_obj->smtp_add);
	fl_clear_browser(smtp_obj->Inc_SMTP_Accts);
	for(i = 0; i < MAX_SMTP_ACCOUNTS; i++) {
		if(*smtp_accounts[i].name == '\0')
			continue;

		fl_add_browser_line(smtp_obj->Inc_SMTP_Accts, get_smtp_acct_line(i));
		if(!bset) {
			fl_set_button(smtp_obj->Inc_SMTP_Acct_Disabled,
						  (smtp_accounts[i].flags & SMTP_DISABLED) ? 1 : 0);
			bset = 1;
		}
	}


	fl_select_browser_line(smtp_obj->Inc_SMTP_Accts, 1);
	fl_unfreeze_form(smtp_obj->smtp_add);

	return;
}
char *get_smtp_acct_line(int smtp_acct) {
	static char smtp_acctline[96];
	struct _smtp_account *smtp;

			smtp = &smtp_accounts[smtp_acct];
			snprintf(smtp_acctline, sizeof(smtp_acctline), 
			 "%s [%s/%s %s]",
					 smtp_accounts[smtp_acct].name, 
			 smtp->hostname, smtp->service,
					 smtp->username); 

	return smtp_acctline;
}

void Inc_SMTP_Acct_Disabled_Call(FL_OBJECT * obj, long param) {
	int i = get_selected_smtp_acct();

	if(i < 0)
		return;

	if(fl_get_button(obj))
		smtp_accounts[i].flags |= SMTP_DISABLED;
	else
		smtp_accounts[i].flags &= ~SMTP_DISABLED;
	return;
}

void Inc_SMTP_Acct_Config_Call (FL_OBJECT * obj, long param) {
	if(ready)
		return;
	ready = 1;
	smtp_obj = create_form_smtp_add();

	display_smtp_accts() ;

	fl_show_form(smtp_obj->smtp_add, FL_PLACE_CENTER, FL_TRANSIENT,
				 "SMTP Server Account List");
	fl_do_only_forms();


	fl_hide_form(smtp_obj->smtp_add);
	fl_free_form(smtp_obj->smtp_add);
	fl_free(smtp_obj);
	smtp_obj = NULL;

	ready = 0;
	return;
}


void Inc_SMTP_Accts_Call(FL_OBJECT * obj, long param) {
	int i = get_selected_smtp_acct();

	if(i < 0)
		return;

	if(fl_mouse_button() == FL_MIDDLE_MOUSE) {
		Inc_SMTP_Acct_Edit_Call(obj, param);
		return;
	}

	fl_set_button(smtp_obj->Inc_SMTP_Acct_Disabled,
				  (smtp_accounts[i].flags & SMTP_DISABLED) ? 1 : 0);

	return;
}









