/* $Id: sign.cpp,v 1.11 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 <glib.h>

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

#define SIGN_XPM
#include "pixmaps.h"

struct _xf_sign {
	char name[16];
	char file[255];
	char rfield[MAX_FIELD_NAME_LEN];
	char rule[127];
	struct _xf_sign *next;
}
xf_sign;

extern cfgfile Config;

static struct _xf_sign *signatures = NULL;
#define SATTACH_BEFORE  -1
#define SATTACH_NONE    0
#define SATTACH_AFTER   1
static int changed = 0;
static struct _xf_sign *ed_sign = NULL;

FL_FORM *signform = NULL;

#define MAX_SIGNATURES  16  /* limit on number of signatures */
#define MAX_SIGN_LEN    2048    /* max. length of signature file */
#define MAX_SIGN_LINES  24  /* max. number of lines in signature */

#define DEF_SIG "----------------------------------\n\
E-Mail: $m\n\
Date: $d\n\
Time: $t\n\
\n\
This message was sent by XFMail\n\
----------------------------------"

static FD_Sign_Edit *sign_obj;
static int ready = 0;

static void save_signatures();

void sign_changed() {
	if(!fl_get_textedit_bufchanged(sign_obj->Sign_Enter))
		return;

	if(!display_msg
	   (MSG_QUEST, "signature", "Signature has been changed, save?"))
		return;

	save_signatures();
}

static void save_signatures() {
	char buf[255], stmp[16];
	struct _xf_sign *sign;
	int i;

	if(ed_sign) {
		snprintf(buf, sizeof(buf), "%s/%s", homedir, ed_sign->file);
		fl_save_textedit(sign_obj->Sign_Enter, buf);

		strncpy(ed_sign->rfield, fl_get_input(sign_obj->Sign_Field),
				MAX_FIELD_NAME_LEN - 1);
		ed_sign->rfield[MAX_FIELD_NAME_LEN - 1] = '\0';

		strncpy(ed_sign->rule, fl_get_input(sign_obj->Sign_Rule), 126);
		ed_sign->rfield[126] = '\0';
	}

	for(i = 1; i <= MAX_SIGNATURES; i++) {
		sprintf(stmp, "sign%d", i);
		Config.remove(stmp);
	}
	i = 0;
	sign = signatures;
	while(sign) {
		i++;
		sprintf(stmp, "sign%d", i);
		snprintf(buf, sizeof(buf), "%s %s %s %s", sign->name, sign->file,
				 sign->rfield, sign->rule);
		Config.set(stmp, buf);
		sign = sign->next;
	}
	Config.save(0);
	return;
}

void load_signatures() {
	int i;
	char buf[255], stmp[255];
	struct _xf_sign *sign, *sign1;
	FILE *sf;

	sign = signatures;
	while(sign) {
		sign1 = sign->next;
		free(sign);
		sign = sign1;
	}

	signatures = NULL;
	ed_sign = NULL;
	changed = 0;

	for(i = 1; i <= MAX_SIGNATURES; i++) {
		sprintf(stmp, "sign%d", i);
		if(!Config.exist(stmp))
			continue;
		strcpy(buf, Config.get(stmp, "").c_str());
		if((sign = (struct _xf_sign *) malloc(sizeof(struct _xf_sign))) ==
		   NULL) {
			display_msg(MSG_FATAL, "load signatures", "Malloc failed");
			return;
		}
		sign->rfield[0] = sign->rule[0] = '\0';
		if(sscanf(buf, "%s %s %s %s",
				  sign->name, sign->file, sign->rfield, sign->rule) < 2) {
			free(sign);
			continue;
		}

		snprintf(buf, sizeof(buf), "%s/%s", homedir, sign->file);
		if(access(buf, R_OK) == -1) {
			display_msg(MSG_WARN, "load sign",
						"%s does not exits, skipping", buf);
			free(sign);
			Config.remove(stmp);
			continue;
		}

		sign->next = signatures;
		signatures = sign;
	}

	if(signatures == NULL) {
		if((sign = (struct _xf_sign *) malloc(sizeof(struct _xf_sign))) ==
		   NULL) {
			display_msg(MSG_FATAL, "load signatures", "Malloc failed");
			return;
		}
		sign->rfield[0] = sign->rule[0] = '\0';
		sign->next = NULL;
		strcpy(sign->name, "default");
		strcpy(sign->file, ".signature");
		snprintf(buf, sizeof(buf), "%s/.signature", homedir);
		if(access(buf, R_OK) == -1) {
			snprintf(buf, sizeof(buf), "%s/.signature.xfmail", homedir);
			strcpy(sign->file, ".signature.xfmail");
			if(access(buf, R_OK) == -1) {
				if((sf = fopen(buf, "w")) == NULL) {
					display_msg(MSG_WARN, "load sign", "Failed to open %s",
								buf);
					free(sign);
					return;
				}
				fputs(DEF_SIG, sf);
				fclose(sf);
			}
		}

		signatures = sign;
		snprintf(buf, sizeof(buf), "%s %s %s %s", sign->name, sign->file,
				 sign->rfield, sign->rule);
		Config.set("sign1", buf);
	}
	return;
}

void free_signatures() {
	struct _xf_sign *sign, *sign1;
	
	sign=signatures;
	while(sign) {
	sign1=sign->next;
	free(sign);
	sign=sign1;
	}		
}
	 

void display_signature() {
	char buf[255];
	struct _xf_sign *sign;
	int sl, i;

	if(!ed_sign || !ready)
		return;

	sign_changed();

	snprintf(buf, sizeof(buf), "%s/%s", homedir, ed_sign->file);
	fl_load_textedit(sign_obj->Sign_Enter, buf);
	fl_set_input(sign_obj->Sign_Field, ed_sign->rfield);
	fl_set_input(sign_obj->Sign_Rule, ed_sign->rule);

	fl_freeze_form(sign_obj->Sign_Edit);
	fl_clear_browser(sign_obj->Sign_List);
	sign = signatures;
	sl = i = 1;
	while(sign) {
		fl_addto_browser(sign_obj->Sign_List, sign->name);
		if(sign == ed_sign)
			sl = i;
		sign = sign->next;
		i++;
	}

	fl_select_browser_line(sign_obj->Sign_List, sl);
	fl_unfreeze_form(sign_obj->Sign_Edit);
	return;
}

void add_sign() {
	int i;
	char stmp[32], *sname, *p, *sfile;
	struct _xf_sign *sign;
	FILE *sf;

	sign_changed();

	for(i = 1; i <= MAX_SIGNATURES; i++) {
		sprintf(stmp, "sign%d", i);
		if(!Config.exist(stmp))
			break;
	}

	if(i == MAX_SIGNATURES) {
		display_msg(MSG_WARN, "add signature",
					"Can not have more then %d sigantures",
					MAX_SIGNATURES);
		return;
	}

	sname = (char *) fl_show_input("Signature name:", "");
	if(!sname || !*sname)
		return;

	if(strlen(sname) > 15) {
		display_msg(MSG_WARN, "add signature", "Signature name too long");
		return;
	}

	p = sname;
	while(*p != '\0') {
		if(!isalpha(*p) && !isdigit(*p)) {
			display_msg(MSG_WARN, "add signature",
						"Invalid character in signature name");
			return;
		}
		p++;
	}

	sign = signatures;
	while(sign) {
		if(!strcmp(sign->name, sname)) {
			display_msg(MSG_WARN, "add signature",
						"Signature %s already exists", sname);
			return;
		}

		sign = sign->next;
	}

	snprintf(stmp, sizeof(stmp), ".signature.%s", sname);

	p =
	(char *) fl_show_file_selector("Signature file", homedir,
								   ".signature*", stmp);

	if(!p)
		return;

	if((sfile = strrchr(p, '/')) == NULL)
		sfile = p;
	else
		sfile++;

	sign = signatures;
	while(sign) {
		if(!strcmp(sign->file, sfile)) {
			display_msg(MSG_WARN, "add signature",
						"File %s already used by signature %s", sfile,
						sign->name);
			return;
		}

		sign = sign->next;
	}

	if(access(p, R_OK) == -1) {
		if(!display_msg
		   (MSG_QUEST, "add signature", "%s does not exists, create?", p))
			return;

		if((sf = fopen(p, "w")) == NULL) {
			display_msg(MSG_WARN, "add signature", "Failed to create %s",
						p);
			return;
		}

		fputs(DEF_SIG, sf);
		fclose(sf);
	}

	if((sign = (struct _xf_sign *) malloc(sizeof(struct _xf_sign))) ==
	   NULL) {
		display_msg(MSG_FATAL, "add signature", "Malloc failed");
		return;
	}

	strcpy(sign->name, sname);
	strcpy(sign->file, sfile);
	sign->rfield[0] = sign->rule[0] = '\0';
	sign->next = signatures;
	signatures = sign;

	ed_sign = sign;
	display_signature();
	changed = 1;

	return;
}

void delete_signature() {
	struct _xf_sign *sign;
	char buf[255], stmp[16], *p;
	int i;

	if(!ed_sign)
		return;

	if(!strcmp(ed_sign->name, "default")) {
		display_msg(MSG_WARN, "Delete signature",
					"Can not delete default signature");
		return;
	}

	if(!display_msg
	   (MSG_QUEST | MSG_DEFNO, "Delete signature",
		"Are you sure want to delete signature %s?", ed_sign->name))
		return;

	snprintf(buf, sizeof(buf), "%s/%s", homedir, ed_sign->file);
	if(access(buf, R_OK) == 0) {
		if(display_msg
		   (MSG_QUEST | MSG_DEFNO, "Delete signature", "Remove %s ?",
			ed_sign->file)) unlink(buf);
	}

	for(i = 1; i <= MAX_SIGNATURES; i++) {
		sprintf(stmp, "sign%d", i);
		if(!Config.exist(stmp))
			continue;
		p = const_cast<char *>(Config.get(stmp, "").c_str());
		if(strncmp(p, ed_sign->name, strlen(ed_sign->name)))
			continue;

		Config.remove(stmp);
		break;
	}

	if(signatures == ed_sign)
		signatures = ed_sign->next;
	else {
		sign = signatures;
		while(sign) {
			if(sign->next == ed_sign) {
				sign->next = ed_sign->next;
				break;
			}
			sign = sign->next;
		}
	}

	free(ed_sign);
	ed_sign = signatures;

	display_signature();
	changed = 1;

	return;
}

void Sign_Enter_Call(FL_OBJECT * obj, long param) {
	changed = 1;
}

void Sign_Rule_Call(FL_OBJECT * obj, long param) {
	changed = 1;
}

void Sign_Field_Call(FL_OBJECT * obj, long param) {
	changed = 1;
}

void Sign_Save_Call(FL_OBJECT * obj, long param) {
	save_signatures();
}

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

void Sign_List_Call(FL_OBJECT * obj, long param) {
	char *sname;
	struct _xf_sign *sign;

	sname = (char *) fl_get_browser_line(obj, fl_get_browser(obj));

	if(!sname || !*sname)
		return;

	sign = signatures;
	while(sign) {
		if(!strcmp(sname, sign->name))
			break;
		sign = sign->next;
	}

	if(!sign) {
		display_msg(MSG_WARN, "Select signature",
					"Can not find signature %s", sname);
		return;
	}

	sign_changed();

	ed_sign = sign;
	display_signature();

	return;
}

void Sign_Add_Call(FL_OBJECT * obj, long param) {
	add_sign();
}

void Sign_Del_Call(FL_OBJECT * obj, long param) {
	delete_signature();
}

FD_Sign_Edit *create_form_Sign_Edit_1(void) {
	FL_OBJECT *obj;
	FD_Sign_Edit *fdui = (FD_Sign_Edit *) fl_calloc(1, sizeof(*fdui));

	fdui->Sign_Edit = fl_bgn_form(FL_NO_BOX, 660, 330);
	obj = fl_add_box(FL_UP_BOX, 0, 0, 660, 330, "");
	fl_set_object_color(obj, FL_MCOL, FL_COL1);
	obj =
	fl_add_labelframe(FL_EMBOSSED_FRAME, 410, 10, 240, 90, "Options");
	fl_set_object_color(obj, FL_BLACK, FL_MCOL);
	fl_set_object_gravity(obj, FL_NorthWest, FL_NoGravity);
	fl_set_object_resize(obj, FL_RESIZE_NONE);
	obj = fl_add_labelframe(FL_EMBOSSED_FRAME, 200, 10, 200, 90, "Rule");
	fl_set_object_color(obj, FL_BLACK, FL_MCOL);
	fl_set_object_gravity(obj, FL_NorthWest, FL_NoGravity);
	fl_set_object_resize(obj, FL_RESIZE_NONE);
	fdui->Sign_Enter = obj =
					   fl_add_textedit(FL_NORMAL_TEXTEDIT, 10, 110, 640, 170, "");
	fl_set_textedit_fontstyle(obj, FL_FIXEDBOLD_STYLE);
	fl_set_object_gravity(obj, FL_NorthWest, FL_SouthEast);
	fl_set_object_callback(obj, Sign_Enter_Call, 0);
	if(Config.getInt("editpastecur", 1))
		fl_set_textedit_flags(obj, FL_TEXTEDIT_PASTE_CUR, -1);
	fdui->Sign_Save = obj =
					  fl_add_pixmapbutton(FL_NORMAL_BUTTON, 50, 290, 35, 33, "");
	fl_set_button_shortcut(obj, "#S", 1);
	fl_set_object_gravity(obj, FL_SouthWest, FL_NoGravity);
	fl_set_object_resize(obj, FL_RESIZE_NONE);
	fl_set_object_callback(obj, Sign_Save_Call, 0);
	fdui->Sign_Exit = obj =
					  fl_add_pixmapbutton(FL_NORMAL_BUTTON, 10, 290, 35, 33, "");
	fl_set_button_shortcut(obj, "#X", 1);
	fl_set_object_gravity(obj, FL_SouthWest, FL_NoGravity);
	fl_set_object_resize(obj, FL_RESIZE_NONE);
	fdui->Sign_Add = obj =
					 fl_add_pixmapbutton(FL_NORMAL_BUTTON, 90, 290, 35, 33, "");
	fl_set_object_gravity(obj, FL_SouthWest, FL_NoGravity);
	fl_set_object_resize(obj, FL_RESIZE_NONE);
	fl_set_object_callback(obj, Sign_Add_Call, 0);
	fdui->Sign_Delete = obj =
						fl_add_pixmapbutton(FL_NORMAL_BUTTON, 130, 290, 35, 33, "");
	fl_set_object_gravity(obj, FL_SouthWest, FL_NoGravity);
	fl_set_object_resize(obj, FL_RESIZE_NONE);
	fl_set_object_callback(obj, Sign_Del_Call, 0);
	fdui->Sign_Att = obj =
					 fl_add_choice(FL_NORMAL_CHOICE, 560, 20, 80, 30, "Add");
	fl_set_object_shortcut(obj, "#A", 1);
	fl_set_object_boxtype(obj, FL_UP_BOX);
	fl_set_object_gravity(obj, FL_NorthWest, FL_NoGravity);
	fl_set_object_resize(obj, FL_RESIZE_NONE);
	fl_set_object_callback(obj, Sign_Att_Call, 0);
	fdui->Sign_Rule = obj =
					  fl_add_input(FL_NORMAL_INPUT, 230, 60, 160, 30, "Text");
	fl_set_input_shortcut(obj, "#T", 1);
	fl_set_object_gravity(obj, FL_NorthWest, FL_NoGravity);
	fl_set_object_resize(obj, FL_RESIZE_NONE);
	fl_set_object_callback(obj, Sign_Rule_Call, 0);
	fdui->Sign_Field = obj =
					   fl_add_input(FL_NORMAL_INPUT, 320, 20, 70, 30, "Field");
	fl_set_input_shortcut(obj, "#F", 1);
	fl_set_object_gravity(obj, FL_NorthWest, FL_NoGravity);
	fl_set_object_resize(obj, FL_RESIZE_NONE);
	fl_set_object_callback(obj, Sign_Field_Call, 0);
	fdui->Sign_Help = obj =
					  fl_add_pixmapbutton(FL_NORMAL_BUTTON, 170, 290, 35, 33, "");
	fl_set_button_shortcut(obj, "#H", 1);
	fl_set_object_gravity(obj, FL_SouthWest, FL_NoGravity);
	fl_set_object_resize(obj, FL_RESIZE_NONE);
	fl_set_object_callback(obj, cb_help_button, 7);
	fdui->Sign_Fortune = obj =
						 fl_add_input(FL_NORMAL_INPUT, 460, 60, 180, 30, "Execute");
	fl_set_input_shortcut(obj, "#E", 1);
	fl_set_object_gravity(obj, FL_NorthWest, FL_NoGravity);
	fl_set_object_resize(obj, FL_RESIZE_NONE);
	fl_set_object_callback(obj, Sign_Rule_Call, 0);
	fdui->Sign_Prefix = obj =
						fl_add_checkbutton(FL_PUSH_BUTTON, 490, 20, 30, 30,
										   "Put '-- '\nbefore");
	fl_set_button_shortcut(obj, "#P", 1);
	fl_set_object_lalign(obj, FL_ALIGN_LEFT);
	fl_set_object_gravity(obj, FL_NorthWest, FL_NoGravity);
	fl_set_object_resize(obj, FL_RESIZE_NONE);
	fl_set_object_callback(obj, Sign_Rule_Call, 0);
	fdui->Sign_List = obj =
					  fl_add_browser(FL_HOLD_BROWSER, 10, 10, 180, 90, "");
	fl_set_object_color(obj, FL_MCOL, FL_YELLOW);
	fl_set_object_gravity(obj, FL_NorthWest, FL_NoGravity);
	fl_set_object_resize(obj, FL_RESIZE_NONE);
	fl_set_object_callback(obj, Sign_List_Call, 0);
	fl_end_form();

	fdui->Sign_Edit->fdui = fdui;

	return fdui;
}

void sign_edit() {
	struct _xf_sign *sign;
	int w, h;
	char geom[16];

	if(ready) {
		XRaiseWindow(fl_display, sign_obj->Sign_Edit->window);
		return;
	}

	ready = 1;
	changed = 0;
	if(!signatures)
		load_signatures();

	ed_sign = NULL;
	sign = signatures;
	while(sign) {
		if(!strcmp(sign->name, "default")) {
			ed_sign = sign;
			break;
		}
		sign = sign->next;
	}

	if(!ed_sign)
		ed_sign = signatures;

	sign_obj = create_form_Sign_Edit_1();

	fl_set_textedit_fontsize(sign_obj->Sign_Enter,
							 Config.getInt("SignatureFSize",
										   FL_NORMAL_SIZE));
	fl_set_textedit_fontstyle(sign_obj->Sign_Enter,
							  Config.getInt("SignatureFStyle",
											FL_NORMAL_STYLE));
	fl_set_textedit_color(sign_obj->Sign_Enter,
						  Config.getInt("SignatureBgCol",
										FL_TOP_BCOL),
						  Config.getInt("SignatureFgCol",
										FL_BLACK), FL_BLUE, 0);
	fl_addto_choice(sign_obj->Sign_Att, "Don't add|Before|After");
	fl_set_choice(sign_obj->Sign_Att,
				  Config.getInt("sattach", 2));
	fl_set_input(sign_obj->Sign_Fortune, Config.get("fortune", "/usr/games/fortune -s").c_str());
	fl_set_button(sign_obj->Sign_Prefix,
				  Config.getInt("signprefix", 1));
	fl_set_pixmapbutton_data(sign_obj->Sign_Exit, exit_xpm);
	sign_obj->Sign_Exit->u_vdata = const_cast < char *>("Exit");
	fl_set_object_posthandler(sign_obj->Sign_Exit, post_handler);
	fl_set_pixmapbutton_data(sign_obj->Sign_Save, save_xpm);
	sign_obj->Sign_Save->u_vdata = const_cast < char *>("Save changes");
	fl_set_object_posthandler(sign_obj->Sign_Save, post_handler);

	fl_set_pixmapbutton_data(sign_obj->Sign_Add, sign_xpm);
	sign_obj->Sign_Add->u_vdata = const_cast < char *>("Add signature");
	fl_set_object_posthandler(sign_obj->Sign_Add, post_handler);

	fl_set_pixmapbutton_data(sign_obj->Sign_Delete, delsign_xpm);
	sign_obj->Sign_Delete->u_vdata =
	const_cast < char *>("Delete signature");
	fl_set_object_posthandler(sign_obj->Sign_Delete, post_handler);

	fl_set_pixmapbutton_data(sign_obj->Sign_Help, help_xpm);
	sign_obj->Sign_Help->u_vdata = const_cast < char *>("Help");
	fl_set_object_posthandler(sign_obj->Sign_Help, post_handler);

	display_signature();

	Config.setFlags("signgeom", CF_NOTCHANGED);
	w = 660;
	h = 330;
	sscanf(Config.get("signgeom", "").c_str(), "%d %d", &w, &h);
	fl_set_form_minsize(sign_obj->Sign_Edit, 400, 200);
	fl_set_form_maxsize(sign_obj->Sign_Edit, 760, 330);
	fl_set_form_size(sign_obj->Sign_Edit, w, h);

	fl_show_form(sign_obj->Sign_Edit, FL_PLACE_FREE, FL_TRANSIENT,
				 "Signature");
	fl_do_only_forms();

	sign_changed();
	Config.set("sattach", fl_get_choice(sign_obj->Sign_Att));
	Config.set("signprefix", fl_get_button(sign_obj->Sign_Prefix));
	Config.set("fortune", (char *) fl_get_input(sign_obj->Sign_Fortune));
	sprintf(geom, "%d %d", sign_obj->Sign_Edit->w,
			sign_obj->Sign_Edit->h);
	Config.set("signgeom", geom);
	fl_hide_form(sign_obj->Sign_Edit);
	fl_free_form(sign_obj->Sign_Edit);
	fl_free(sign_obj);
	sign_obj = NULL;

	ready = 0;
	changed = 0;
	return;
}

char *get_sign_file(struct _mail_msg *msg) {
	static char sfile[255];
	struct _xf_sign *sign, *dsign;
	struct _xf_rule rule;

#ifdef HAVE_REGCOMP
	regex_t rx;
	char errbuf[2048];
	int regerr;
#endif

	if(signform)
		return pup_choose_sign(signform);

	if(!signatures) {
		load_signatures();
		if(!signatures)
			return NULL;
	}

	init_rule(&rule);

	dsign = sign = signatures;
	while(sign) {
		if(!strcmp(sign->name, "default")) {
			dsign = sign;
			if(msg == NULL)
				break;

			sign = sign->next;
			continue;
		}

		if(msg == NULL) {
			sign = sign->next;
			continue;
		}

		if(!strlen(sign->rfield) || !strlen(sign->rule)) {
			sign = sign->next;
			continue;
		}

		strcpy(rule.fmatch, sign->rfield);
#ifdef HAVE_REGCOMP
		if((regerr = regcomp(&rx, sign->rule, REG_EXTENDED | REG_ICASE))) {
			regerror(regerr, &rx, errbuf, sizeof(errbuf));
			display_msg(MSG_WARN, "Invalid regular expression", "%s",
						errbuf);
			regfree(&rx);
			sign = sign->next;
			continue;
		}
		rule.rx = rx;
#else
		strncpy(rule.tmatch, sign->rule, 254);
		rule.tmatch[254];
#endif

		if(match_rule(msg, &rule)) {
#ifdef HAVE_REGCOMP
			regfree(&rx);
#endif
			dsign = sign;
			break;
		}

		sign = sign->next;
	}

	msg->free_text(msg);
	if(!dsign)
		return NULL;

	snprintf(sfile, sizeof(sfile), "%s/%s", homedir, dsign->file);

	return sfile;
}

char *pup_choose_sign(FL_FORM * form) {
	static char sfile[255];
	int fpup, i;
	struct _xf_sign *sign;

	if(!signatures) {
		load_signatures();
		if(!signatures)
			return NULL;
	}

	fpup = fl_newpup(form ? form->window : main_form->window);
	fl_addtopup(fpup, "Signatures %t");
	sign = signatures;
	while(sign) {
		fl_addtopup(fpup, sign->name);
		sign = sign->next;
	}

	i = fl_dopup(fpup);
	fl_freepup(fpup);
	if(i <= 0)
		return NULL;

	sign = signatures;
	i--;
	while(i && sign) {
		i--;
		sign = sign->next;
	}

	if(!sign)
		return NULL;

	snprintf(sfile, sizeof(sfile), "%s/%s", homedir, sign->file);

	return sfile;
}
