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


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

#define MAX_ELEMENTS    64

#define XFORMS_USER_FONT_START	16
#define XFORMS_USER_FONT_MAX	47

#define MAXFONT_NAME_LENGTH		256

extern cfgfile Config;

static FL_FORM *form;

static FL_OBJECT
* textobj, *styleobj, *sizeobj, *placeobj, *bg_obj, *fg_obj;

extern FL_OBJECT *b_folders, *b_messages, *msgpane;
static int ready = 0;
static int nfonts = 0;
static FD_config_intern *charset_obj;
static int cchanged = 0;

typedef struct _size_el {
	char el_name[16];
	char el_descr[32];
	FL_OBJECT **el_obj;
	u_int type;
#define NO_TYPE 0x00
#define BROWSER 0x01
#define MENU    0x02
#define FONT    0x03
#define XFDEF   0x04
#define XTEXT   0x05
#define NO_SIZE     0x10
#define NO_STYLE    0x20
#define NO_BGCOL    0x40
#define NO_FGCOL    0x80
#define N_RESTART   0x100
	u_int def_size, def_style, def_bg, def_fg;
}
size_el;

struct _size_el elements[MAX_ELEMENTS] = {

	{"Folders", "Folder browser", &b_folders, BROWSER, FL_NORMAL_SIZE,
		FL_FIXED_STYLE, FL_COL1, FL_YELLOW},
	{"Messages", "Message browser", &b_messages, BROWSER, FL_NORMAL_SIZE,
		FL_FIXED_STYLE, FL_COL1, FL_YELLOW},
	{"ChooseFolder", "Folder chooser", NULL, NO_TYPE, FL_NORMAL_SIZE,
		FL_FIXED_STYLE, FL_COL1, FL_YELLOW},
	{"AddrBook", "Address book", NULL, NO_TYPE, FL_NORMAL_SIZE,
		FL_FIXED_STYLE, FL_COL1, FL_YELLOW},
	{"Signature", "Signature editor", NULL, NO_TYPE, FL_NORMAL_SIZE,
		FL_FIXED_STYLE, FL_COL1, FL_BLACK},
	{"View", "Message viewer", &msgpane, XTEXT, FL_NORMAL_SIZE,
		FL_NORMAL_STYLE, FL_COL1, FL_BLACK},
	{"Edit", "Message editor", NULL, NO_TYPE, FL_NORMAL_SIZE,
		FL_NORMAL_STYLE, FL_COL1, FL_BLACK},
	{"InputFont", "Input box font size", NULL,
		XFDEF | NO_STYLE | NO_BGCOL | NO_FGCOL | N_RESTART, FL_DEFAULT_SIZE,
		FL_NORMAL_STYLE, FL_WHITE, FL_BLACK},
	{"LabelFont", "Label font size", NULL,
		XFDEF | NO_STYLE | NO_BGCOL | NO_FGCOL | N_RESTART, FL_DEFAULT_SIZE,
		FL_NORMAL_STYLE, FL_WHITE, FL_BLACK},
	{"ChoiceFont", "Choice font size", NULL,
		XFDEF | NO_STYLE | NO_BGCOL | NO_FGCOL | N_RESTART, FL_DEFAULT_SIZE,
		FL_NORMAL_STYLE, FL_WHITE, FL_BLACK},
	{"MenuFont", "Menu font size", NULL,
		XFDEF | NO_STYLE | NO_BGCOL | NO_FGCOL | N_RESTART, FL_DEFAULT_SIZE,
		FL_NORMAL_STYLE, FL_WHITE, FL_BLACK},
	{"BrowserFont", "Browser font size", NULL,
		XFDEF | NO_STYLE | NO_BGCOL | NO_FGCOL | N_RESTART, FL_DEFAULT_SIZE,
		FL_NORMAL_STYLE, FL_WHITE, FL_BLACK},
	{"ButtonFont", "Button font size", NULL,
		XFDEF | NO_STYLE | NO_BGCOL | NO_FGCOL | N_RESTART, FL_DEFAULT_SIZE,
		FL_NORMAL_STYLE, FL_WHITE, FL_BLACK},
	{"PopUpFont", "PopUp font size", NULL,
		XFDEF | NO_STYLE | NO_BGCOL | NO_FGCOL | N_RESTART, FL_DEFAULT_SIZE,
		FL_NORMAL_STYLE, FL_WHITE, FL_BLACK},
	{"SliderFont", "Slider font size", NULL,
		XFDEF | NO_STYLE | NO_BGCOL | NO_FGCOL | N_RESTART, FL_DEFAULT_SIZE,
		FL_NORMAL_STYLE, FL_WHITE, FL_BLACK},
	{"GoodiesFont", "Dialogs font size", NULL,
		NO_BGCOL | NO_FGCOL | N_RESTART, FL_DEFAULT_SIZE, FL_NORMAL_STYLE,
		FL_WHITE, FL_BLACK},
	{"_", "_", NULL, NO_TYPE, FL_NORMAL_SIZE, FL_FIXED_STYLE, FL_COL1,
		FL_YELLOW}
};

struct _charset_fonts {
	int code;
	const char *registry, *encoding;
	int style, size;
};

struct _charset_fonts supp_charsets_fonts[] = {
	{ US_ASCII,	"ascii", "0", FL_FIXEDBOLD_STYLE, FL_MEDIUM_SIZE },
	{ ISO_8859_1, "iso8859", "1", FL_FIXEDBOLD_STYLE, FL_MEDIUM_SIZE },
	{ ISO_8859_2, "iso8859", "2", FL_FIXEDBOLD_STYLE, FL_MEDIUM_SIZE },
	{ ISO_8859_3, "iso8859", "3", FL_FIXEDBOLD_STYLE, FL_MEDIUM_SIZE },
	{ ISO_8859_4, "iso8859", "4", FL_FIXEDBOLD_STYLE, FL_MEDIUM_SIZE },
	{ ISO_8859_5, "iso8859", "5", FL_FIXEDBOLD_STYLE, FL_MEDIUM_SIZE },
	{ ISO_8859_6, "iso8859", "6", FL_FIXEDBOLD_STYLE, FL_MEDIUM_SIZE },
	{ ISO_8859_7, "iso8859", "7", FL_FIXEDBOLD_STYLE, FL_MEDIUM_SIZE },
	{ ISO_8859_8, "iso8859", "8", FL_FIXEDBOLD_STYLE, FL_MEDIUM_SIZE },
	{ ISO_8859_9, "iso8859", "9", FL_FIXEDBOLD_STYLE, FL_MEDIUM_SIZE },
	{ ISO_8859_10, "iso8859", "10", FL_FIXEDBOLD_STYLE, FL_MEDIUM_SIZE },
	{ ISO_8859_13, "iso8859", "13", FL_FIXEDBOLD_STYLE, FL_MEDIUM_SIZE },
	{ ISO_8859_14, "iso8859", "14", FL_FIXEDBOLD_STYLE, FL_MEDIUM_SIZE },
	{ ISO_8859_15, "iso8859", "15", FL_FIXEDBOLD_STYLE, FL_MEDIUM_SIZE },
	{ KOI8R, "koi8", "r", FL_FIXEDBOLD_STYLE, FL_MEDIUM_SIZE },
};

#define XFMAIL_INTERNAL_FONTS	(sizeof(supp_charsets_fonts) / sizeof(supp_charsets_fonts[0]))

static char font_table[XFORMS_USER_FONT_MAX][MAXFONT_NAME_LENGTH];

void display_styles();
void display_charsets();

static int save_font_iterator = 0;
static void save_font(const char *f) {

	if (save_font_iterator >= XFORMS_USER_FONT_START)
		return;

	snprintf(font_table[save_font_iterator],
		sizeof(font_table[save_font_iterator]), "%s", f);
	save_font_iterator++;
}

static void build_custom_font(unsigned int cfont) {
	char buf[MAXFONT_NAME_LENGTH];
	char *p, *p2;

	snprintf(buf, sizeof(buf), "%s",
		font_table[supp_charsets_fonts[cfont].style]);

	/* replace the last two XFLD fields with our own registry & encoding */
	if ((p = strrchr(buf, '-')) != NULL) {
		*p = '\0';
		if ((p2 = strrchr(buf, '-')) != NULL) {
			*(++p2) = '\0';
			strcat(buf, supp_charsets_fonts[cfont].registry);
			strcat(buf, "-");
			strcat(buf, supp_charsets_fonts[cfont].encoding);
		} else
			*p = '-';
	}
	if (fl_set_font_name(cfont + XFORMS_USER_FONT_START, buf) < 0)
		/* no such font, default to using original font */
		fl_set_font_name(cfont + XFORMS_USER_FONT_START,
			font_table[supp_charsets_fonts[cfont].style]);
}

static void build_custom_fonts() {
	unsigned int i;
		
	/* save internal fonts so that we can build custom ones
	 * from them.
	 */
	save_font_iterator = 0;
	fl_enumerate_fonts(save_font, 0);

	for (i = 0; i < XFMAIL_INTERNAL_FONTS; i++)
		build_custom_font(i);
}

void restore_fonts() {
	int i;
	char fname[16];

	for(nfonts = 0, i = XFORMS_USER_FONT_START + XFMAIL_INTERNAL_FONTS;
		i < XFORMS_USER_FONT_MAX; i++) {
		snprintf(fname, sizeof(fname), "Font%d", i);
		if(Config.exist(fname)) {
			if(fl_set_font_name(i, Config.get(fname, "").c_str()) < 0) {
				display_msg(MSG_LOG, "font", "font %s can not be loaded",
							Config.get(fname, "").c_str());
				Config.remove(fname);
				break;
			} else {
				snprintf(font_table[XFORMS_USER_FONT_START +
						XFMAIL_INTERNAL_FONTS + nfonts], MAXFONT_NAME_LENGTH,
					"%s", Config.get(fname,"").c_str());
				nfonts++;
			}
		} else
			break;
	}

	return;
}

void restore_charsets() {
	unsigned int k = 0;
	char cname[MAX_CHARSET_NAME + 10];

	for (k = 0; k < XFMAIL_INTERNAL_FONTS; k++) {
		/* get font style */
		snprintf(cname, sizeof(cname), "%sFStyle",
			charset_name_from_code(supp_charsets_fonts[k].code));
		supp_charsets_fonts[k].style = Config.getInt(cname,
			supp_charsets_fonts[k].style);

		/* get font size */
		snprintf(cname, sizeof(cname), "%sFSize",
			charset_name_from_code(supp_charsets_fonts[k].code));
		supp_charsets_fonts[k].size = Config.getInt(cname,
			supp_charsets_fonts[k].size);
	}
	restore_fonts();
	build_custom_fonts();

	def_encoding = Config.getInt("encoding", DEFAULT_ENCODING);
	def_charset = Config.getInt("charset", DEFAULT_CHARSET);
	return;
}

void font_add(FL_OBJECT * obj, long arg) {
	char *p;	
	int i;
	char *str, fname[16];
	
	if(XFORMS_USER_FONT_START + XFMAIL_INTERNAL_FONTS + nfonts >=
		XFORMS_USER_FONT_MAX) {
		display_msg(MSG_WARN, "FONTS",
			"Can not use more then %d different fonts",
			XFORMS_USER_FONT_MAX);
		return;
	}

	str = (char *) fl_show_input("Enter X-Windows font name", "");

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

	i = 0;
	p = str;
	while((p = strchr(p, '-')) != NULL) {
		p++;
		i++;
		if(i == 8) {
			if(*p == '*')
				*p = '?';

			break;
		}
	}

	
	if(fl_set_font_name(XFORMS_USER_FONT_START + XFMAIL_INTERNAL_FONTS
			+ nfonts, str) < 0) {
		display_msg(MSG_WARN, "Invalid font", "%s", str);
		return;
	}

	snprintf(font_table[XFORMS_USER_FONT_START + XFMAIL_INTERNAL_FONTS + nfonts],
		MAXFONT_NAME_LENGTH, "%s", str);
	sprintf(fname, "Font%d", XFORMS_USER_FONT_START +
		XFMAIL_INTERNAL_FONTS + nfonts);
	Config.set(fname, str);
	
	nfonts++;
	display_styles();
	return;
}

void font_del(FL_OBJECT * obj, long arg) {
	char fname[32];
	unsigned int i;

	if(nfonts <= 0) {
		display_msg(MSG_WARN, "FONT", "Can not delete predefined font");
		return;
	}

	i = 0;
	while(strlen(elements[i].el_name) > 2) {
		snprintf(fname, sizeof(fname), "%sFStyle", elements[i].el_name);

		if(Config.getInt(fname, elements[i].def_style) ==
			XFORMS_USER_FONT_START + XFMAIL_INTERNAL_FONTS + (nfonts - 1)) {
			display_msg(MSG_WARN, "FONT",
				"The font is in use. Can not delete");
			return;
		}
		i++;
	}

	nfonts--;
	sprintf(fname, "Font%d", XFORMS_USER_FONT_START + XFMAIL_INTERNAL_FONTS +
		nfonts);
	Config.remove(fname);
	display_styles();
}

void display_size(int el_num) {
	char buf[64];
	int size, style, bgcol, fgcol;
	int i, type, typef;

	type = elements[el_num].type;
	typef = type & 0xff0;
	type &= 0x0f;

	size = elements[el_num].def_size;
	style = elements[el_num].def_style;
	bgcol = elements[el_num].def_bg;
	fgcol = elements[el_num].def_fg;

	if(typef & NO_SIZE)
		fl_deactivate_object(sizeobj);
	else {
		fl_activate_object(sizeobj);
		snprintf(buf, sizeof(buf), "%sFSize", elements[el_num].el_name);
		size = Config.getInt(buf, size);
		if(size == 0)
			size = FL_DEFAULT_SIZE;
	}

	if(typef & NO_STYLE)
		fl_deactivate_object(styleobj);
	else {
		fl_activate_object(styleobj);
		snprintf(buf, sizeof(buf), "%sFStyle", elements[el_num].el_name);
		style = Config.getInt(buf, style);
	}

	if(typef & NO_BGCOL)
		fl_deactivate_object(bg_obj);
	else {
		if((type == BROWSER) && elements[el_num].el_obj
		   && *elements[el_num].el_obj)
			bgcol = (*elements[el_num].el_obj)->col1;
		else
			if((type == XTEXT) && elements[el_num].el_obj
			   && *elements[el_num].el_obj) bgcol =
			(*elements[el_num].el_obj)->col2;

		snprintf(buf, sizeof(buf), "%sBgCol", elements[el_num].el_name);
		bgcol = Config.getInt(buf, bgcol);
		fl_activate_object(bg_obj);
	}

	if(typef & NO_FGCOL)
		fl_deactivate_object(fg_obj);
	else {
		if((type == BROWSER) && elements[el_num].el_obj
		   && *elements[el_num].el_obj)
			fgcol = (*elements[el_num].el_obj)->col2;
		else
			if((type == XTEXT) && elements[el_num].el_obj
			   && *elements[el_num].el_obj) fgcol =
			(*elements[el_num].el_obj)->col1;

		snprintf(buf, sizeof(buf), "%sFgCol", elements[el_num].el_name);
		fgcol = Config.getInt(buf, fgcol);
		fl_activate_object(fg_obj);
	}

	if(type == FONT) {
		fgcol = Config.getInt("ViewFgCol", fgcol);
		bgcol = Config.getInt("ViewBgCol", bgcol);
	}

	fl_select_browser_line(styleobj, style + 1);

	switch(size) {
		case 8:
			i = 1;
			break;
		case 10:
			i = 2;
			break;
		case 11:
			i = 3;
			break;
		case 12:
			i = 4;
			break;
		case 13:
			i = 5;
			break;
		case 14:
			i = 6;
			break;
		case 18:
			i = 7;
			break;
		case 24:
			i = 8;
			break;
		case 30:
			i = 9;
			break;
		default:
			i = 1;
			break;
	}

	fl_select_browser_line(sizeobj, i);

	/* If the user has selected a custom font style, or the font is
	 * one for the character sets, then display the custom font instead.
	 */
	if (type == FONT)
		style += XFORMS_USER_FONT_START;

	fl_set_object_lstyle(textobj, style);
	fl_set_object_lsize(textobj, size);
	fl_set_object_color(textobj, bgcol, textobj->col2);
	fl_set_object_lcol(textobj, fgcol);
	fl_redraw_object(textobj);

	return;
}

void color_cb(FL_OBJECT * obj, long arg) {
	char buf[64];
	FL_COLOR col = fl_show_colormap(arg ? textobj->col1 : textobj->lcol);
	int num = fl_get_browser(placeobj) - 1, type;

	type = elements[num].type & 0x0f;

	if(arg)
		fl_set_object_color(textobj, col, textobj->col2);
	else
		fl_set_object_lcol(textobj, col);

	if(type == FONT) {
		display_size(num);
		return;
	}

	snprintf(buf, sizeof(buf), "%sBgCol", elements[num].el_name);
	Config.set(buf, textobj->col1);
	snprintf(buf, sizeof(buf), "%sFgCol", elements[num].el_name);
	Config.set(buf, textobj->lcol);
	if((type == BROWSER) && elements[num].el_obj && *elements[num].el_obj) {
		fl_activate_object(*elements[num].el_obj);
		fl_set_object_color(*elements[num].el_obj, textobj->col1,
							textobj->lcol);
		fl_redraw_object(*elements[num].el_obj);
	} else
		if((type == XTEXT) && elements[num].el_obj
		   && *elements[num].el_obj) {
		fl_activate_object(*elements[num].el_obj);
		fl_set_textedit_color(*elements[num].el_obj, textobj->col1,
							  textobj->lcol, -1, 1);
	}

	display_size(num);

	return;
}

void place_cb(FL_OBJECT * obj, long arg) {
	display_size(fl_get_browser(placeobj) - 1);
}

void style_cb(FL_OBJECT * obj, long arg) {
	char buf[64];
	int num = fl_get_browser(placeobj) - 1;
	int style = fl_get_browser(obj) - 1, type;

	/* determine whether this is a user font */
	if (style >= XFORMS_USER_FONT_START)
		style += XFMAIL_INTERNAL_FONTS;

	type = elements[num].type & 0x0f;
	snprintf(buf, sizeof(buf), "%sFStyle", elements[num].el_name);
	Config.set(buf, style);
	if(elements[num].type & N_RESTART)
		fl_show_message("Warning!", "This change will take effect",
						"after you restart XFMail");

	if(type == FONT) {
		int code = charset_code_from_name(elements[num].el_name);
		unsigned int i;
		for (i = 0; i < XFMAIL_INTERNAL_FONTS; i++)
			if (supp_charsets_fonts[i].code == code)
				break;

		if (i != XFMAIL_INTERNAL_FONTS) {
			supp_charsets_fonts[i].style = style;
			if (style < XFORMS_USER_FONT_START)
				build_custom_font(i);
			else
				fl_set_font_name(XFORMS_USER_FONT_START + i,
					font_table[style]);
		}
	}

	if((type == BROWSER) && elements[num].el_obj && *elements[num].el_obj) {
		fl_set_browser_fontstyle(*elements[num].el_obj, style);
		fl_set_object_lstyle(*elements[num].el_obj, style);
		fl_redraw_object(*elements[num].el_obj);
	} else
		if((type == XTEXT) && elements[num].el_obj
		   && *elements[num].el_obj) {
		fl_set_textedit_fontstyle(*elements[num].el_obj, style);
		fl_set_object_lstyle(*elements[num].el_obj, style);
		fl_redraw_object(*elements[num].el_obj);
	}

	display_size(num);
}

void size_cb(FL_OBJECT * obj, long arg) {
	char buf[64];
	int num = fl_get_browser(placeobj) - 1;
	int size = FL_DEFAULT_SIZE, type;

	type = elements[num].type & 0x0f;
	switch(fl_get_browser(obj)) {
		case 1:
			size = 8;
			break;
		case 2:
			size = 10;
			break;
		case 3:
			size = 11;
			break;
		case 4:
			size = 12;
			break;
		case 5:
			size = 13;
			break;
		case 6:
			size = 14;
			break;
		case 7:
			size = 18;
			break;
		case 8:
			size = 24;
			break;
		case 9:
			size = 30;
			break;
	}

	if(type == FONT) {
		int code = charset_code_from_name(elements[num].el_name);
		unsigned int i;
		for (i = 0; i < XFMAIL_INTERNAL_FONTS; i++)
			if (supp_charsets_fonts[i].code == code)
				break;

		if (i != XFMAIL_INTERNAL_FONTS)
			supp_charsets_fonts[i].size = size;
	}

	snprintf(buf, sizeof(buf), "%sFSize", elements[num].el_name);
	Config.set(buf, size);
	if(elements[num].type & N_RESTART)
		fl_show_message("Warning!", "This change will take effect",
						"after you restart XFMail");

	display_size(num);

	if((type == BROWSER) && elements[num].el_obj && *elements[num].el_obj) {
		fl_set_browser_fontsize(*elements[num].el_obj, size);
		fl_set_object_lsize(*elements[num].el_obj, size);
		fl_redraw_object(*elements[num].el_obj);
	} else
		if((type == XTEXT) && elements[num].el_obj
		   && *elements[num].el_obj) {
		fl_set_textedit_fontsize(*elements[num].el_obj, size);
		fl_set_object_lsize(*elements[num].el_obj, size);
		fl_redraw_object(*elements[num].el_obj);
	}

	return;
}

void create_form_form(void) {
	FL_OBJECT *obj;

	form = fl_bgn_form(FL_NO_BOX, 550, 300);
	fl_add_box(FL_FLAT_BOX, 0, 0, 550, 300, "");
	textobj = obj =
			  fl_add_text(FL_NORMAL_TEXT, 10, 10, 530, 100,
						  "XFMail\nCopyright (c) 1995-1998 by\n Gennady B. Sorokopud\n\374\314\305\313\324\322\317\316\316\301\321 \320\317\336\324\301\n\351\360\345\370\350\367\354\340 \370\340\345\343");
	fl_set_object_boxtype(obj, FL_FRAME_BOX);
	fl_set_object_lalign(obj, FL_ALIGN_CENTER | FL_ALIGN_INSIDE);
	fl_set_object_color(obj, FL_INDIANRED, FL_YELLOW);
	fl_set_object_dblbuffer(obj, 1);
	styleobj = obj =
			   fl_add_browser(FL_HOLD_BROWSER, 10, 120, 180, 130, "");
	fl_set_object_color(obj, FL_TOP_BCOL, FL_YELLOW);
	fl_set_object_callback(obj, style_cb, 0);
	sizeobj = obj =
			  fl_add_browser(FL_HOLD_BROWSER, 200, 120, 170, 130, "");
	fl_set_object_color(obj, FL_TOP_BCOL, FL_YELLOW);
	fl_set_object_callback(obj, size_cb, 0);
	placeobj = obj =
			   fl_add_browser(FL_HOLD_BROWSER, 380, 120, 160, 130, "");
	fl_set_object_color(obj, FL_TOP_BCOL, FL_YELLOW);
	fl_set_object_callback(obj, place_cb, 0);

	bg_obj = fl_add_button(FL_NORMAL_BUTTON, 330, 260, 70, 30, "Bg Col");
	fl_set_object_callback(bg_obj, color_cb, 1);

	fg_obj = fl_add_button(FL_NORMAL_BUTTON, 410, 260, 70, 30, "Fg Col");
	fl_set_object_callback(fg_obj, color_cb, 0);

	obj = fl_add_button(FL_RETURN_BUTTON, 10, 260, 70, 30, "Ok");

	obj = fl_add_button(FL_NORMAL_BUTTON, 90, 260, 70, 30, "Help");
	fl_set_button_shortcut(obj, "#H", 1);
	fl_set_object_callback(obj, cb_help_button, 15);

	obj = fl_add_button(FL_NORMAL_BUTTON, 170, 260, 70, 30, "Add");
	fl_set_object_callback(obj, font_add, 0);

	obj = fl_add_button(FL_NORMAL_BUTTON, 250, 260, 70, 30, "Delete");
	fl_set_object_callback(obj, font_del, 0);

	fl_end_form();
}

void create_the_forms(void) {
	create_form_form();
}

static void get_short_font_name(const char *xfld, char *buf, size_t buflen)
{
	char buf2[MAXFONT_NAME_LENGTH];
	char *p, *p1, *p2;

	strcpy(buf2, xfld);
	p1 = p = strchr(buf2 + 1, '-');
	p2 = strchr(p + 1, '-');
	p = strchr(p2 + 1, '-');
	p2 = strchr(p + 1, '-');
	*p2 = '\0';
	snprintf(buf, buflen, "%s", p1 + 1);
}

void display_styles() {
	char buf[MAXFONT_NAME_LENGTH];
	int i = fl_get_browser(styleobj);
	int k;

	if(i == 0)
		i = 1;

	fl_freeze_form(form);
	fl_clear_browser(styleobj);

	/* display the builtin fonts */
	for (k = 0; k < XFORMS_USER_FONT_START; k++) {
		/* display just the short name */
		get_short_font_name(font_table[k], buf, sizeof(buf));

		fl_add_browser_line(styleobj, buf);
	}

	/* display user added fonts */
	for (k = XFORMS_USER_FONT_START + XFMAIL_INTERNAL_FONTS;
		 k < XFORMS_USER_FONT_START + XFMAIL_INTERNAL_FONTS + nfonts; k++)
		fl_add_browser_line(styleobj, font_table[k]);

	fl_select_browser_line(styleobj, i);
	fl_unfreeze_form(form);
}

void set_el_size() {
	FL_IOPT cntl;
	struct _size_el *sz = elements;
	char chdescr[32];
	int i = 0, sep, xfdefs;
	unsigned int k;

	if(ready)
		return;

	fl_get_defaults(&cntl);

	create_the_forms();
	ready = 1;
	xfdefs = -1;

	while(sz->el_name[0] != '_') {
		if((xfdefs == -1) && ((sz->type & 0x0f) == XFDEF))
			xfdefs = i;

		fl_add_browser_line(placeobj, sz->el_descr);
		i++;
		sz++;
	}

	k = 0;
	sep = i;
	for (k = 0; k < XFMAIL_INTERNAL_FONTS; k++, i++) {
		if(i >= MAX_ELEMENTS) {
			display_msg(MSG_WARN, "FONTS",
				"Too many charsets, can't display");
			break;
		}

		strcpy(elements[i].el_name, charset_name_from_code(supp_charsets_fonts[k].code));
		strcpy(elements[i].el_descr, charset_descr_from_code(supp_charsets_fonts[k].code));
		elements[i].el_obj = NULL;
		elements[i].type = FONT | NO_FGCOL | NO_BGCOL;
		elements[i].def_style = supp_charsets_fonts[k].style;
		elements[i].def_size = supp_charsets_fonts[k].size;
		elements[i].def_bg = FL_COL1;
		elements[i].def_fg = FL_BLACK;
		snprintf(chdescr, sizeof(chdescr), "%s (%s)", elements[i].el_name,
				 elements[i].el_descr);
		fl_add_browser_line(placeobj, chdescr);
	}

	if(xfdefs >= 0) {
		if(cntl.inputFontSize > 0)
			elements[xfdefs++].def_size = cntl.inputFontSize;
		if(cntl.labelFontSize > 0)
			elements[xfdefs++].def_size = cntl.labelFontSize;
		if(cntl.choiceFontSize > 0)
			elements[xfdefs++].def_size = cntl.choiceFontSize;
		if(cntl.menuFontSize > 0)
			elements[xfdefs++].def_size = cntl.menuFontSize;
		if(cntl.browserFontSize > 0)
			elements[xfdefs++].def_size = cntl.browserFontSize;
		if(cntl.buttonFontSize > 0)
			elements[xfdefs++].def_size = cntl.buttonFontSize;
		if(cntl.pupFontSize > 0)
			elements[xfdefs++].def_size = cntl.pupFontSize;
		if(cntl.sliderFontSize > 0)
			elements[xfdefs++].def_size = cntl.sliderFontSize;
	}

	display_styles();

	fl_addto_browser(sizeobj, "8 (small)");
	fl_addto_browser(sizeobj, "10(normal1)");
	fl_addto_browser(sizeobj, "11(scaled)");
	fl_addto_browser(sizeobj, "12(normal2)");
	fl_addto_browser(sizeobj, "13(scaled)");
	fl_addto_browser(sizeobj, "14(normal2)");
	fl_addto_browser(sizeobj, "18(large)");
	fl_addto_browser(sizeobj, "24(Huge)");
	fl_addto_browser(sizeobj, "30(scaled)");

	fl_select_browser_line(sizeobj, 2);
	fl_select_browser_line(placeobj, 1);
	fl_select_browser_line(styleobj, 1);
	display_size(0);

	fl_show_form(form, FL_PLACE_CENTER, FL_TRANSIENT, "Fonts & Colors");

	fl_do_only_forms();
	elements[sep].el_name[0] = '_';

	fl_hide_form(form);
	fl_free_form(form);
	ready = 0;
	return;

}

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

void CHSET_AAlias_Call(FL_OBJECT * obj, long param) {
	char *p, aname[MAX_CHARSET_NAME + 1], adescr[MAX_CHARSET_NAME + 1],
	buf[127];
	int i = fl_get_browser(charset_obj->CHSET_Select);

	if(i < 1)
		return;
	i--;

	if(is_charset_alias(supp_charsets[i].charset_name)) {
		display_msg(MSG_WARN, "add charset alias",
					"Can not make alias to alias");
		return;
	}

	snprintf(buf, sizeof(buf), "New alias name of charset %s:",
			 supp_charsets[i].charset_name);
	p = (char *) fl_show_input(buf, "");
	if(!p || !*p)
		return;

	if(strlen(p) > MAX_CHARSET_NAME) {
		display_msg(MSG_WARN, "add charset alias",
					"charset name can not be longer then %d characters",
					MAX_CHARSET_NAME);
		return;
	}

	strncpy(aname, p, MAX_CHARSET_NAME);
	aname[MAX_CHARSET_NAME] = '\0';
	p = aname;
	while(*p != '\0') {
		if(!isgraph(*p)) {
			display_msg(MSG_WARN, "add charset alias",
						"invalid character in charset name");
			return;
		}
		p++;
	}

	p = (char *) fl_show_input("Enter charset description:", "");
	if(!p || !*p)
		return;

	if(strlen(p) > MAX_CHARSET_NAME) {
		display_msg(MSG_WARN, "add charset alias",
					"charset description can not be longer then %d characters",
					MAX_CHARSET_NAME);
		return;
	}

	strncpy(adescr, p, MAX_CHARSET_NAME);
	adescr[MAX_CHARSET_NAME] = '\0';
	p = adescr;
	while(*p != '\0') {
		if(!isgraph(*p) || (*p == ' ')) {
			display_msg(MSG_WARN, "add charset alias",
						"invalid character in charset description");
			return;
		}
		p++;
	}

	if(add_charset(aname, adescr, supp_charsets[i].charset_code) != 0)
		return;

	display_charsets();
	cchanged = 1;

	return;
}

void CHSET_DAlias_Call(FL_OBJECT * obj, long param) {
	int i = fl_get_browser(charset_obj->CHSET_Select);

	if(i < 1)
		return;
	i--;

	if(!is_charset_alias(supp_charsets[i].charset_name)) {
		display_msg(MSG_WARN, "delete charset alias",
					"Only charset aliases can be deleted");
		return;
	}

	if(del_charset(supp_charsets[i].charset_name) != 0)
		return;

	display_charsets();
	cchanged = 1;

	return;
}

void display_charsets() {
	char buf[255];
	int i, k;

	i = 0;
	fl_freeze_form(charset_obj->config_intern);
	fl_clear_browser(charset_obj->CHSET_Select);
	while(supp_charsets[i].charset_code != CHAR_UNKNOWN) {
		k = is_charset_alias(supp_charsets[i].charset_name);
		snprintf(buf, sizeof(buf), "%-12.12s %-22.22s%-11.11s",
				 supp_charsets[i].charset_name,
				 supp_charsets[i].charset_descr ? supp_charsets[i].
				 charset_descr : "",
				 k > 0 ? supp_charsets[k - 1].charset_name : "");
		fl_add_browser_line(charset_obj->CHSET_Select, buf);
		i++;
	}
	fl_select_browser_line(charset_obj->CHSET_Select, 1);
	fl_unfreeze_form(charset_obj->config_intern);

	return;
}

void charset_conf(int set_default, FD_config_intern * form) {
	cchanged = 0;
	charset_obj = form;
	fl_set_browser_fontstyle(charset_obj->CHSET_Select, FL_FIXED_STYLE);
	fl_set_browser_fontsize(charset_obj->CHSET_Select, FL_NORMAL_SIZE);
	display_charsets();
}

void handle_charsets_input(FD_config_intern * form) {
	char buf[255], aname[MAX_CHARSET_NAME + 10];
	int i, k;

	charset_obj = form;
	if(cchanged) {
		i = 0;
		while(supp_charsets[i].charset_code != CHAR_UNKNOWN) {
			if(is_charset_alias(supp_charsets[i].charset_name)) {
				i++;
				continue;
			}

			k = i + 1;
			buf[0] = '\0';
			while(supp_charsets[k].charset_code != CHAR_UNKNOWN) {
				if(supp_charsets[k].flags & CHARSET_FIXED) {
					k++;
					continue;
				}
				if(supp_charsets[k].charset_code ==
				   supp_charsets[i].charset_code) {
					if(*buf)
						strcat(buf, " ");
					strcat(buf, supp_charsets[k].charset_name);
					strcat(buf, " ");
					strcat(buf, supp_charsets[k].charset_descr);
				}
				k++;
			}
			snprintf(aname, sizeof(aname), "%sAlias",
					 supp_charsets[i].charset_name);
			if(*buf)
				Config.set(aname, buf);
			else {
				if(Config.exist(aname))
					Config.remove(aname);
			}
			i++;
		}
	}
}

int charset_style_from_code(int code) {
	unsigned int i;

	for (i = 0; i < XFMAIL_INTERNAL_FONTS; i++) {
		if (supp_charsets_fonts[i].code == code)
			return (int)i + XFORMS_USER_FONT_START;
	}
	return -1;
}

int charset_size_from_code(int code) {
	unsigned int i;

	for (i = 0; i < XFMAIL_INTERNAL_FONTS; i++) {
		if (supp_charsets_fonts[i].code == code)
			return supp_charsets_fonts[i].size;
	}
	return -1;
}
