//  resource.cc for bbsmount - an tool for mounting in X11
//
//  Copyright (c) 2001 by Miroslav Jezbera, jezberam@upcase.inf.upol.cz
//
//  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., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// (See the included file COPYING / GPL-2.0)
//

#if HAVE_CONFIG_H
#   include "config.h"
#endif /* HAVE_CONFIG_H */

#ifdef    HAVE_STDARG_H
#  include <stdarg.h>
#endif // HAVE_STDARG_H

#include <ctype.h>
#include <string.h>
#if HAVE_LOCALE_H
#   include <locale.h>
#endif /* HAVE_LOCALE_H */

#include <algorithm>

using namespace std;

#include "resource.hh"
#include "bbsmount.hh"
#include "blackboxstyle.hh"
#include "i18n.hh"

/* Hack */
#if !HAVE_STRCASESTR
#   define strcasestr	strstr
#endif /* !HAVE_STRCASESTR */

#ifndef   FONT_ELEMENT_SIZE
#define   FONT_ELEMENT_SIZE 50
#endif // FONT_ELEMENT_SIZE

const int modifiers_count = 8;
const unsigned int max_button_number = 5;

const char *modifiers[modifiers_count] = {
    "Shift",
    "Lock",
    "Control",
    "Mod1",
    "Mod2",
    "Mod3",
    "Mod4",
    "Mod5"
};

const int modifiers_mask[modifiers_count] = {
    ShiftMask,
    LockMask,
    ControlMask,
    Mod1Mask,
    Mod2Mask,
    Mod3Mask,
    Mod4Mask,
    Mod5Mask
};

Resource::Resource(ToolWindow *toolwindow): 
  BaseResource(toolwindow)
{
    mounts_count = 0;
    mounts = NULL;
    tooltip.font = NULL;
    tooltip.fontset = NULL;
    tooltip.fontset_extents = NULL;
    Load();
}

Resource::~Resource()
{
    Clean();
}

void Resource::Clean()
{
    CleanMounts();
    if (tooltip.font) {
	XFreeFont(bbtool->getXDisplay(), tooltip.font);
	tooltip.font = NULL;
    }
    if (tooltip.fontset) {
	XFreeFontSet(bbtool->getXDisplay(), tooltip.fontset);
	tooltip.fontset = NULL;
    }
}

void Resource::CleanMounts(void) {

    for (; mounts_count > 0; mounts_count--) {
	free(mounts[mounts_count - 1].mount_point);
	XpmFreeXpmImage(&mounts[mounts_count - 1].mounted);
	XpmFreeXpmImage(&mounts[mounts_count - 1].not_mounted);
    }
    if (mounts) {
	free(mounts);
	mounts = NULL;
    }
}

void Resource::LoadBBToolResource(void)
{
/*    XrmValue value;
    char *value_type;

    if (XrmGetResource(resource_db, "bbsmount.autoConfig",
		"Bbsmount.Autoconfig", &value_type, &value))
	if (! strncasecmp("true", value.addr, value.size))
	    style.auto_config = True;
	else
	    style.auto_config = False;
    else
	style.auto_config = False;*/

    SizeAndPosition();
	
    Frame();
    App();
    ImagePrefix();
    Tooltip();
	
    // bbsmount specific options
    MountPoints();
}


void Resource::Frame()
{
    XrmValue value;
    char *value_type;

    readTexture("bbsmount.frame", "Bbsmount.Frame", BB_FRAME, "Toolbar", "slategrey", "darkslategrey",
	    "Raised Gradient Vertical Bevel1", &frame.texture);
	
    if (XrmGetResource(resource_db, "bbsmount.bevelWidth","Bbsmount.BevelWidth", &value_type, &value)) {
	if (sscanf(value.addr, "%u", &frame.bevelWidth) != 1)
	    frame.bevelWidth = 4;
	else
	    if (frame.bevelWidth == 0)
		frame.bevelWidth = 4;
    }
    else
	if (XrmGetResource(resource_db, BB_BEVELWIDTH,"BevelWidth", &value_type, &value)) {
	    if (sscanf(value.addr, "%u", &frame.bevelWidth) != 1)
		frame.bevelWidth = 4;
	    else
		if (frame.bevelWidth == 0)
		    frame.bevelWidth = 4;
	}
	else
	    frame.bevelWidth = 4;
}


void Resource::SizeAndPosition()
{
	XrmValue value;
	char *value_type;
	unsigned int w,h;
	char positionstring[11];

  if (!(bbtool->withdrawn))
  {
  	if (XrmGetResource(resource_db, "bbsmount.withdrawn",
		     "Bbsmount.Withdrawn", &value_type, &value))
    {
  		if (! strncasecmp("true", value.addr, value.size))
	  		bbtool->withdrawn = True;
	    else
		  	bbtool->withdrawn = False;
  	}	
	  else
		  bbtool->withdrawn = False;
  }

  if (!(bbtool->shape))
  {
  	if (XrmGetResource(resource_db, "bbsmount.shape",
		     "Bbsmount.Shape", &value_type, &value))
    {
  		if (! strncasecmp("true", value.addr, value.size))
	  		bbtool->shape = True;
	    else
		  	bbtool->shape = False;
  	}	
	  else
		  bbtool->shape = bbtool->withdrawn;
  }

  
	if (!(bbtool->position))
	{
		if (!(XrmGetResource(resource_db, "bbsmount.position","Bbsmount.Position",
							&value_type, &value)))
			strncpy(positionstring, "-0-0", 5);
		else
			strncpy(positionstring, value.addr, strlen(value.addr)+1);
	}
	else
		strncpy(positionstring, bbtool->position, strlen(bbtool->position)+1);


	position.mask=XParseGeometry(positionstring, &position.x, &position.y, &w, &h);
	if (!(position.mask & XValue))
		position.x=0;
	if (!(position.mask & YValue))
		position.y=0;

	/* need this to compute the height */
/*	const char *defaultFont = "-*-helvetica-medium-r-*-*-*-120-*-*-*-*-*-*";
	
	if (frame.font)
	{
    	XFreeFont(bbtool->dpy, frame.font);
		frame.font = 0;
	}
	
	if (XrmGetResource(resource_db, "bbsmount.heightBy.font","Bbsmount.heightBy.Font",
						&value_type, &value))
	{
    	if ((frame.font = XLoadQueryFont(bbtool->dpy, value.addr)) == NULL)
		{
    		fprintf(stderr, " blackbox: couldn't load font '%s'\n"
	      					" ...  reverting to default font.", value.addr);
	    	if ((frame.font = XLoadQueryFont(bbtool->dpy, defaultFont)) == NULL)
			{
				fprintf(stderr,"blackbox: couldn't load default font.  please check to\n"
								"make sure the necessary font is installed '%s'\n",
					defaultFont);
				exit(2);
			}
		}
	}
	else if (XrmGetResource(resource_db, BB_FONT,"TitleFont", &value_type, &value))
	{
		if ((frame.font = XLoadQueryFont(bbtool->dpy, value.addr)) == NULL)
		{
    		fprintf(stderr, " blackbox: couldn't load font '%s'\n"
	      					" ...  reverting to default font.", value.addr);
			if ((frame.font = XLoadQueryFont(bbtool->dpy, defaultFont)) == NULL)
			{
				fprintf(stderr,
					"blackbox: couldn't load default font.  please check to\n"
					"make sure the necessary font is installed '%s'\n",
					defaultFont);
				exit(2);
			}
		}
	}
	else 
	{
    	if ((frame.font = XLoadQueryFont(bbtool->dpy, defaultFont)) == NULL)
		{
			fprintf(stderr,
	      			"blackbox: couldn't load default font.  please check to\n"
	      			"make sure the necessary font is installed '%s'\n", defaultFont);
			exit(2);
		}
	}*/
}
	
//void Resource::Label(void)
//{
//	XrmValue value;
//	char *value_type;
//
//	/* text-label resources */
//	if (XrmGetResource(resource_db, "bbsmount.label.transparent",
//		     "Bbsmount.label.Transparent", &value_type, &value))
//	{
//		if (! strncasecmp("true", value.addr, value.size))
//			label.transparent = True;
//	    else
//			label.transparent = False;
//	}	
//	else
//		label.transparent = False;
//	
//	readDatabaseTexture("bbsmount.label", "Bbsmount.Label",BB_LABEL,"Toolbar.Label",
//                      "slategrey","darkslategrey",
//                      BImage_Sunken|BImage_Gradient|BImage_Vertical|
//                      BImage_Bevel1,&label.texture);
//
//		readDatabaseColor("bbsmount..textColor",
//      								"Bbsmount.TextColor",
//                      BB_LABEL_TEXTCOLOR, "Toolbar.TextColor",
//                      "LightGrey",&label.textColor);
//
//    
//	const char *defaultFont = "-*-helvetica-medium-r-*-*-*-120-*-*-*-*-*-*";
//	
//	if (label.font)
//	{
//		XFreeFont(bbtool->dpy, label.font);
//		label.font = 0;
//	}
//	
//	if (XrmGetResource(resource_db, "bbsmount.label.font", "Bbsmount.Label.Font",
//						&value_type, &value))
//	{
//		if ((label.font = XLoadQueryFont(bbtool->dpy, value.addr)) == NULL)
//		{
//    	fprintf(stderr, " blackbox: couldn't load font '%s'\n"
//	      							" ...  reverting to default font.", value.addr);
//		    if ((label.font = XLoadQueryFont(bbtool->dpy, defaultFont)) == NULL)
//			{
//				fprintf(stderr,
//					"blackbox: couldn't load default font.  please check to\n"
//					"make sure the necessary font is installed '%s'\n",
//					defaultFont);
//			exit(2);
//			}
//		}
//	}
//	else if  (XrmGetResource(resource_db, BB_FONT, "TitleFont", &value_type, &value))
//	{
//		if ((label.font = XLoadQueryFont(bbtool->dpy, value.addr)) == NULL)
//		{
//			fprintf(stderr, " blackbox: couldn't load font '%s'\n"
//	      					" ...  reverting to default font.", value.addr);
//			if ((label.font = XLoadQueryFont(bbtool->dpy, defaultFont)) == NULL)
//			{
//				fprintf(stderr,
//					"blackbox: couldn't load default font.  please check to\n"
//					"make sure the necessary font is installed '%s'\n",
//					defaultFont);
//				exit(2);
//			}
//		}
//	}
//	else
//	{
//		if ((label.font = XLoadQueryFont(bbtool->dpy, defaultFont)) == NULL)
//		{
//			fprintf(stderr,"blackbox: couldn't load default font.  please check to\n"
//				    "make sure the necessary font is installed '%s'\n", defaultFont);
//			exit(2);
//		}
//	}
//}

void Resource::App()
{
    XrmValue value;
    char *value_type;

    if (XrmGetResource(resource_db, "bbsmount.columns", "Bbsmount.Columns", &value_type, &value)) {
	if (sscanf(value.addr, "%u", &app.columns) != 1)
	    app.columns = 1;
	else
	    if (app.columns == 0)
		app.columns = 1;
    }
    else
	app.columns = 1;

    if (XrmGetResource(resource_db, "bbsmount.rows", "Bbsmount.Rows", &value_type, &value)) {
	if (sscanf(value.addr, "%u", &app.rows) != 1)
	    app.rows = 1;
	else
	    if (app.rows == 0)
		app.rows = 1;
    }
    else
	app.rows = 1;

    if (XrmGetResource(resource_db, "bbsmount.column.width", "Bbsmount.Column.Width", &value_type, &value)) {
	if (sscanf(value.addr, "%u", &app.column_width) != 1)
	    app.column_width = 32;
	else
	    if (app.column_width == 0)
		app.column_width = 32;
    }
    else
	app.column_width = 32;

    if (XrmGetResource(resource_db, "bbsmount.row.height", "Bbsmount.Row.Height", &value_type, &value)) {
	if (sscanf(value.addr, "%u", &app.row_height) != 1)
	    app.row_height = 32;
	else
	    if (app.row_height == 0)
		app.row_height = 32;
    }
    else
	app.row_height = 32;

	readTexture("bbsmount.mount", "Bbsmount.Mount",BB_LABEL,"Toolbar.Button",
                      "slategrey","darkslategrey",
                      "Raised Gradient Vertical Bevel1", &app.mount_texture);
	readTexture("bbsmount.mount.pressed", "Bbsmount.Mount.Pressed",BB_LABEL,"Toolbar.Button.Pressed",
                      "slategrey","darkslategrey",
                      "Sunken Gradient Vertical Bevel1", &app.mount_texture_pressed);
    if (XrmGetResource(resource_db, "bbsmount.buttonpadding","Bbsmount.ButtonPadding", &value_type, &value)) {
	if (sscanf(value.addr, "%u", &app.button_padding) != 1)
	    app.button_padding = 2;
    }
    else
	app.button_padding = 2;
    if (XrmGetResource(resource_db, "bbsmount.checkdelay", "Bbsmount.CheckDelay", &value_type, &value)) {
	if (sscanf(value.addr, "%u", &app.button_padding) != 1)
	    app.refresh_time = 1;
	else
	    if (app.refresh_time == 0)
		app.refresh_time = 1;
    }
    else
	app.refresh_time = 1;
    if (XrmGetResource(resource_db, "bbsmount.debuglevel", "Bbsmount.DebugLevel", &value_type, &value)) {
	if (sscanf(value.addr, "%u", &debug_level) != 1)
	    debug_level = 2;
    }
    else
	debug_level = 2;
}

void Resource::ImagePrefix(void)
{
    XrmValue value;
    char *value_type;

    if (XrmGetResource(resource_db, "bbsmount.imageprefix", "Bbsmount.ImagePrefix", &value_type, &value)) {
	image_prefix = value.addr;
    }
    else
	image_prefix = "";
}

void
Resource::Tooltip(void)
{
	XrmValue value;
	char *value_type;

	readTexture("bbsmount.tooltip","Bbsmount.ToolTip", BB_TOOLTIP, "Window.Label.Focus",
	            "slategrey","darkslategrey",
	            "Flat Gradient Diagonal Bevel1", &tooltip.texture);

	readColor("bbsmount.tooltip.borderColor","Bbsmount.ToolTip.BorderColor",
	          BB_BORDERCOLOR,"BorderColor",
	          "DarkGrey",&tooltip.borderColor);

	readColor("bbsmount.tooltip.textColor","Bbsmount.ToolTip.TextColor",
	          BB_MENU_TEXTCOLOR,"Menu.Frame.TextColor",
	          "LightGrey",&tooltip.textColor);

	if (XrmGetResource(resource_db, "bbsmount.tooltip.bevelWidth",
			   "Bbsmount.ToolTip.BevelWidth", &value_type, &value)) {
		if (sscanf(value.addr, "%u", &tooltip.bevelWidth) != 1)
			tooltip.bevelWidth = 2;
	} else
		tooltip.bevelWidth = 2;

	if (XrmGetResource(resource_db, "bbsmount.tooltip.borderWidth",
			   "Bbsmount.ToolTip.BorderWidth", &value_type, &value)) {
		if (sscanf(value.addr, "%u", &tooltip.borderWidth) != 1)
			tooltip.borderWidth = 1;
	} else
		tooltip.borderWidth = 1;

	if (XrmGetResource(resource_db, "bbsmount.tooltip.timeout",
			   "Bbsmount.ToolTip.Timeout", &value_type, &value)) {
		if (sscanf(value.addr, "%u", &tooltip.timeout) != 1)
			tooltip.timeout = 0;
	} else
		tooltip.timeout = 0;

	/* need this to compute the height */
	const char *defaultFont = "-*-helvetica-medium-r-*-*-*-120-*-*-*-*-*-*";

	if (tooltip.font) {
		XFreeFont(bbtool->getXDisplay(), tooltip.font);
		tooltip.font = NULL;
	}
	if (tooltip.fontset) {
		XFreeFontSet(bbtool->getXDisplay(), tooltip.fontset);
		tooltip.fontset = NULL;
		tooltip.fontset_extents = NULL;
	}

	if (XrmGetResource(resource_db, "bbsmount.tooltip.font","Bbsmount.ToolTip.Font",
			   &value_type, &value)) {
		if (i18n.multibyte()) {
			if ((tooltip.fontset = createFontSet(value.addr)) == NULL) {
				fprintf(stderr, " blackbox: couldn't load font '%s'\n"
					" ...  reverting to default font.", value.addr);
				if ((tooltip.fontset = createFontSet(defaultFont)) == NULL) {
					fprintf(stderr, "blackbox: couldn't load default font.  please check to\n"
						"make sure the necessary font is installed '%s'\n",
						defaultFont);
					exit(2);
				}
			}
			tooltip.fontset_extents = XExtentsOfFontSet(tooltip.fontset);
		} else {
			if ((tooltip.font = XLoadQueryFont(bbtool->getXDisplay(), value.addr)) == NULL) {
				fprintf(stderr, " blackbox: couldn't load font '%s'\n"
					" ...  reverting to default font.", value.addr);
				if ((tooltip.font = XLoadQueryFont(bbtool->getXDisplay(), defaultFont)) == NULL) {
					fprintf(stderr,"blackbox: couldn't load default font.  please check to\n"
						"make sure the necessary font is installed '%s'\n",
						defaultFont);
					exit(2);
				}
			}
		}
	} else {
		if (XrmGetResource(resource_db, BB_FONT,"TitleFont", &value_type, &value)) {
			if (i18n.multibyte()) {
				if ((tooltip.fontset = createFontSet(value.addr)) == NULL) {
					fprintf(stderr, " blackbox: couldn't load font '%s'\n"
						" ...  reverting to default font.", value.addr);
					if ((tooltip.fontset = createFontSet(defaultFont)) == NULL) {
						fprintf(stderr, "blackbox: couldn't load default font.  please check to\n"
							"make sure the necessary font is installed '%s'\n",
							defaultFont);
						exit(2);
					}
				}
			} else {
				if ((tooltip.font = XLoadQueryFont(bbtool->getXDisplay(), value.addr)) == NULL) {
					fprintf(stderr, " blackbox: couldn't load font '%s'\n"
						" ...  reverting to default font.", value.addr);
					if ((tooltip.font = XLoadQueryFont(bbtool->getXDisplay(), defaultFont)) == NULL) {
						fprintf(stderr,
							"blackbox: couldn't load default font.  please check to\n"
							"make sure the necessary font is installed '%s'\n",
							defaultFont);
						exit(2);
					}
				}
			}
		} else {
			if (i18n.multibyte()) {
				if ((tooltip.fontset = createFontSet(defaultFont)) == NULL) {
					fprintf(stderr, "blackbox: couldn't load default font.  please check to\n"
						"make sure the necessary font is installed '%s'\n",
						defaultFont);
					exit(2);
				}
			} else {
				if ((tooltip.font = XLoadQueryFont(bbtool->getXDisplay(), defaultFont)) == NULL) {
					fprintf(stderr,
						"blackbox: couldn't load default font.  please check to\n"
						"make sure the necessary font is installed '%s'\n", defaultFont);
					exit(2);
				}
			}
		}
	}
}

//void Resource::Show()
//{
//	XrmValue value;
//	char *value_type;
//
// 	if (XrmGetResource(resource_db, "bbsmount.show.euStyle",
//		     "Bbsmount.show.EuStyle", &value_type, &value))
//	{
//    	if (! strncasecmp("true", value.addr, value.size))
//    	{
//				report.euStyle = True;
//  		}
//	    else
//    		report.euStyle = False;
//	}
//	else
//		report.euStyle = False;
// 
//	/* what to show.resources */
//}
/*void Resource::MountPoints(void)
{
	XrmValue value;
	char *value_type;
	char str1[30], str2[30];
	int mount_counter = 1;
	bool next = true;

	CleanMounts();
	while (next) {
	    sprintf(str1, "bbsmount.mount%u", mount_counter);
	    sprintf(str2, "Bbsmount.Mount%u", mount_counter);
	    if (XrmGetResource(resource_db, str1, str2, &value_type, &value)) {
		if (!strncasecmp("true", value.addr, value.size)) {
		    mounts = (MOUNT_POINT *)(++mounts_count > 1 ? realloc((void *)mounts, sizeof(MOUNT_POINT) * mounts_count) :
			    malloc(sizeof(MOUNT_POINT)));
		    sprintf(str1, "bbsmount.mount%u.mountpoint", mount_counter);
		    sprintf(str2, "Bbsmount.Mount%u.MountPoint", mount_counter);
		    if (XrmGetResource(resource_db, str1, str2, &value_type, &value)) {
			mounts[mounts_count - 1].mount_point = strdup(value.addr);
		    }
		    else {
			if (--mounts_count)
			    mounts = (MOUNT_POINT *)realloc((void *)mounts, sizeof(MOUNT_POINT) * mounts_count);
			else
			    mounts = NULL;
			continue;
		    }
		    sprintf(str1, "bbsmount.mount%u.mounted", mount_counter);
		    sprintf(str2, "Bbsmount.Mount%u.Mounted", mount_counter);
		    if (XrmGetResource(resource_db, str1, str2, &value_type, &value)) {
			XpmReadFileToXpmImage(value.addr, &mounts[mounts_count - 1].mounted, NULL);
		    }
		    sprintf(str1, "bbsmount.mount%u.notmounted", mount_counter);
		    sprintf(str2, "Bbsmount.Mount%u.NotMounted", mount_counter);
		    if (XrmGetResource(resource_db, str1, str2, &value_type, &value)) {
			XpmReadFileToXpmImage(value.addr, &mounts[mounts_count - 1].not_mounted, NULL);
		    }

		    sprintf(str1, "bbsmount.mount%u.eject", mount_counter);
		    sprintf(str2, "Bbsmount.Mount%u.Eject", mount_counter);
		    if (XrmGetResource(resource_db, str1, str2, &value_type, &value))
			if (!strncasecmp("true", value.addr, value.size))
			    mounts[mounts_count - 1].can_eject = true;
			else
			    mounts[mounts_count - 1].can_eject = false;
		    else
			mounts[mounts_count - 1].can_eject = false;

		    sprintf(str1, "bbsmount.mount%u.close", mount_counter);
		    sprintf(str2, "Bbsmount.Mount%u.Close", mount_counter);
		    if (XrmGetResource(resource_db, str1, str2, &value_type, &value))
			if (!strncasecmp("true", value.addr, value.size))
			    mounts[mounts_count - 1].can_close = true;
			else
			    mounts[mounts_count - 1].can_close = false;
		    else
			mounts[mounts_count - 1].can_close = false;
		}
		else
		    next = false;
	    }
	    else
		next = false;
	    mount_counter++;
	}
}*/

const string &
Resource::GetImagePrefix(void) const
{
    return image_prefix;
}

const vector<MountPoint> &
Resource::GetMountPoints(void) const
{
    return mount_points;
}

const vector<string> &
Resource::GetCommands(void) const
{
    return commands;
}

const vector<string> &
Resource::getInfoTexts(void) const
{
    return infotexts;
}

const vector<string> &
Resource::GetImages(void) const
{
    return images;
}

void
Resource::FreeAll(void)
{
    images.clear();
    commands.clear();
    infotexts.clear();
    mount_points.clear();
    image_prefix.erase();
}

void
Resource::MountPoints(void)
{
    LoadImages();
    LoadCommands();
    LoadInfoTexts();
    LoadMountPoints();
}

void
Resource::LoadImages(void)
{
    XrmValue value;
    char *value_type, str1[30], str2[30];
    bool exists = true;
    int image_counter = 1;
    
    images.clear();
    do {
	sprintf(str1, "bbsmount.image%u", image_counter);
	sprintf(str2, "Bbsmount.Image%u", image_counter);
	if (XrmGetResource(resource_db, str1, str2, &value_type, &value)) {
	    images.push_back(string(value.addr));
#if DEBUG
	    if (debug_level >= dbg_all_work)
		printf("Saving image path nr. %d (%s).\n", image_counter, value.addr);
#endif /* DEBUG */
	}
	else
	    exists = false;
	image_counter++;
    } while (exists);
    
#if DEBUG
    if (debug_level >= dbg_summary)
	printf("%d image definitions found.\n", image_counter - 2);
#endif /* DEBUG */
}

void
Resource::LoadCommands(void)
{
    XrmValue value;
    char *value_type, str1[32], str2[32];
    bool exists = true;
    int command_counter = 1;
    
    commands.clear();
    commands.push_back("");
    do {
	sprintf(str1, "bbsmount.command%u", command_counter);
	sprintf(str2, "Bbsmount.Command%u", command_counter);
	if (XrmGetResource(resource_db, str1, str2, &value_type, &value)) {
	    commands.push_back(string(value.addr));
#if DEBUG
	    if (debug_level >= dbg_all_work)
		printf("Saving command nr. %d (%s).\n", command_counter, value.addr);
#endif /* DEBUG */
	}
	else
	    exists = false;
	command_counter++;
    } while (exists);
    
#if DEBUG
    if (debug_level >= dbg_summary)
	printf("%d commands found.\n", command_counter - 2);
#endif /* DEBUG */
}

void
Resource::LoadInfoTexts(void)
{
    XrmValue value;
    char *value_type, str1[32], str2[32];
    bool exists = true;
    int infotext_counter = 1;
    
    infotexts.clear();
    infotexts.push_back("");
    do {
	sprintf(str1, "bbsmount.infotext%u", infotext_counter);
	sprintf(str2, "Bbsmount.InfoText%u", infotext_counter);
	if (XrmGetResource(resource_db, str1, str2, &value_type, &value)) {
	    infotexts.push_back(string(value.addr));
#if DEBUG
	    if (debug_level >= dbg_all_work)
		printf("Saving infotext nr. %d (%s).\n", infotext_counter, value.addr);
#endif /* DEBUG */
	}
	else
	    exists = false;
	infotext_counter++;
    } while (exists);
    
#if DEBUG
    if (debug_level >= dbg_summary)
	printf("%d infotexts found.\n", infotext_counter - 2);
#endif /* DEBUG */
}

void
Resource::LoadMountPoints(void)
{
    XrmValue value;
    char *value_type, str1[45], str2[45];
    bool exists = true;
    int mountpoint_counter = 1;
    unsigned int image_number;
    
    mount_points.clear();
    do {
	sprintf(str1, "bbsmount.mount%u", mountpoint_counter);
	sprintf(str2, "Bbsmount.Mount%u", mountpoint_counter);
	if (XrmGetResource(resource_db, str1, str2, &value_type, &value)) {
	    mount_points.push_back(MountPoint(string(value.addr)));
	    LoadActions(mountpoint_counter);
	    LoadInfoText(mountpoint_counter);
	    sprintf(str1, "bbsmount.mount%u.mountedimage", mountpoint_counter);
	    sprintf(str2, "Bbsmount.Mount%u.MountedImage", mountpoint_counter);
	    if (XrmGetResource(resource_db, str1, str2, &value_type, &value)) {
		if (sscanf(value.addr, "%u", &image_number) == 1 && image_number <= images.size())
		    mount_points.back().SetMountedImage(image_number);
#if DEBUG
		else
		    printf("Image number assigned to mount point nr. %d is not correct (%s)!\n", mountpoint_counter, value.addr);
#endif /* DEBUG */
	    }
#if DEBUG
	    else
		if (debug_level >= dbg_warning)
		    printf("Mount point nr. %d don't have assigned mounted image!\n", mountpoint_counter);
#endif /* DEBUG */
	    sprintf(str1, "bbsmount.mount%u.notmountedimage", mountpoint_counter);
	    sprintf(str2, "Bbsmount.Mount%u.NotMountedImage", mountpoint_counter);
	    if (XrmGetResource(resource_db, str1, str2, &value_type, &value)) {
		if (sscanf(value.addr, "%u", &image_number) == 1 && image_number <= images.size())
		    mount_points.back().SetNotMountedImage(image_number);
#if DEBUG
		else
		    printf("Image number assigned to mount point nr. %d is not correct (%s)!\n", mountpoint_counter, value.addr);
#endif /* DEBUG */
	    }
#if DEBUG
	    else
		if (debug_level >= dbg_warning)
		    printf("Mount point nr. %d don't have assigned not mounted image!\n", mountpoint_counter);
#endif /* DEBUG */
	    sprintf(str1, "bbsmount.mount%u.description", mountpoint_counter);
	    sprintf(str2, "Bbsmount.Mount%u.Description", mountpoint_counter);
	    if (XrmGetResource(resource_db, str1, str2, &value_type, &value)) {
		mount_points.back().setDescription(value.addr);
	    }
#if DEBUG
	    if (debug_level >= dbg_all_work)
		printf("Loading data about mount point nr. %d.\n", mountpoint_counter);
#endif /* DEBUG */
	}
	else
	    exists = false;
	mountpoint_counter++;
    } while (exists);
    
#if DEBUG
    if (debug_level >= dbg_summary)
	printf("%d mount point definitions found.\n", mountpoint_counter - 2);
#endif /* DEBUG */
}

void
Resource::LoadActions(const int mount_point)
{
    XrmValue value;
    char *value_type, str1[54], str2[54];
    bool exists = true;
    int action_counter = 1;
    unsigned int number, number2;
    set<unsigned int> positive_mod, negative_mod;
    int command_m = 0, command_n = 0, button = 0;

    do {
	positive_mod.clear();
	negative_mod.clear();
	sprintf(str1, "bbsmount.mount%u.action%u.command", mount_point, action_counter);
	sprintf(str2, "Bbsmount.Mount%u.Action%u.Command", mount_point, action_counter);
	if (XrmGetResource(resource_db, str1, str2, &value_type, &value)) {
	    if (sscanf(value.addr, "%u,%u", &number, &number2) == 2 && number < commands.size() && number2 < commands.size()) {
		command_n = number;
		command_m = number2;
	    }
	    else {
		if (sscanf(value.addr, "%u", &number) == 1 && number < commands.size()) {
		    command_n = number;
		    command_m = number;
#if DEBUG
		    if (debug_level >= dbg_all_work)
			printf("Only one command found -- setting it to both mounted/not mounted commands.\n");
#endif /* DEBUG */
		}
		else {
#if DEBUG
		    printf("Command number(s) assigned to mount point nr. %d is not correct (%s)!\n", mount_point, value.addr);
#endif /* DEBUG */
		    continue;
		}
	    }
	}
	else
	    exists = false;
	sprintf(str1, "bbsmount.mount%u.action%u.button", mount_point, action_counter);
	sprintf(str2, "Bbsmount.Mount%u.Action%u.Button", mount_point, action_counter);
	if (XrmGetResource(resource_db, str1, str2, &value_type, &value)) {
	    if (!exists) {
		exists = true;
		continue;
	    }
	    if (sscanf(value.addr, "%u", &number) == 1 && number > 0 && number < max_button_number)
		button = number;
	    else {
#if DEBUG
		printf("Button number assigned to mount point nr. %d is not correct (%s)!\n", mount_point, value.addr);
#endif /* DEBUG */
		continue;
	    }
	}
	else
	    exists = false;
	if (exists) {
	    Action new_action;
	    
	    new_action.SetButton(button);
	    new_action.SetCommand(command_m, true);
	    new_action.SetCommand(command_n, false);
	    sprintf(str1, "bbsmount.mount%u.action%u.modifiers", mount_point, action_counter);
	    sprintf(str2, "Bbsmount.Mount%u.Action%u.Modifiers", mount_point, action_counter);
	    if (XrmGetResource(resource_db, str1, str2, &value_type, &value)) {
		GetModifiers(value.addr, positive_mod, negative_mod);
		set<unsigned int>::iterator pointer;

		for (pointer = positive_mod.begin(); pointer != positive_mod.end(); pointer++)
		    new_action.AddModifier(*pointer);
		for (pointer = negative_mod.begin(); pointer != negative_mod.end(); pointer++)
		    new_action.AddNegativeModifier(*pointer);
#if DEBUG
		if (debug_level >= dbg_summary)
		    printf("%u positive and %u negative modifiers added to action nr %d.\n", positive_mod.size(), negative_mod.size(), action_counter);
#endif /* DEBUG */
	    }

	    mount_points.back().AddAction(new_action);
	}
	action_counter++;
    } while (exists);

#if DEBUG
    if (debug_level >= dbg_summary)
	printf("%d actions found for mount point nr %d.\n", action_counter - 2, mount_point);
#endif /* DEBUG */
}

void
Resource::LoadInfoText(const int mount_point)
{
    XrmValue value;
    char *value_type, str1[54], str2[54];
    unsigned int number;

    sprintf(str1, "bbsmount.mount%u.mountedtext", mount_point);
    sprintf(str2, "Bbsmount.Mount%u.MountedText", mount_point);
    if (XrmGetResource(resource_db, str1, str2, &value_type, &value)) {
	if (sscanf(value.addr, "%u", &number) == 1 && number < infotexts.size())
	    mount_points.back().setMountedInfo(number);
#if DEBUG
	else
	    printf("Infotext number assigned to mount point nr. %d is not correct (%s)!\n", mount_point, value.addr);
#endif /* DEBUG */
    }
    sprintf(str1, "bbsmount.mount%u.notmountedtext", mount_point);
    sprintf(str2, "Bbsmount.Mount%u.NotMountedText", mount_point);
    if (XrmGetResource(resource_db, str1, str2, &value_type, &value)) {
	if (sscanf(value.addr, "%u", &number) == 1 && number < infotexts.size())
	    mount_points.back().setNotMountedInfo(number);
#if DEBUG
	else
	    printf("Infotext number assigned to mount point nr. %d is not correct (%s)!\n", mount_point, value.addr);
#endif /* DEBUG */
    }
    sprintf(str1, "bbsmount.mount%u.errortext", mount_point);
    sprintf(str2, "Bbsmount.Mount%u.ErrorText", mount_point);
    if (XrmGetResource(resource_db, str1, str2, &value_type, &value)) {
	if (sscanf(value.addr, "%u", &number) == 1 && number < infotexts.size())
	    mount_points.back().setErrorInfo(number);
#if DEBUG
	else
	    printf("Infotext number assigned to mount point nr. %d is not correct (%s)!\n", mount_point, value.addr);
#endif /* DEBUG */
    }
}

void
Resource::GetModifiers(const string str, set<unsigned int> &positive, set<unsigned int> &negative) const
{
    int start = 0, stop = 0;
    bool is_negative = false;
    const char **result;
    
    while (start < (int)str.length()) {
	if (isalnum(str[start])) {
	    stop = start + 1;
	    while (stop <= (int)str.length() && isalnum(str[stop]))
		stop++;
	    const_cast<char **>(result) = find(modifiers, modifiers + modifiers_count, str.substr(start, stop - start));
	    if (result < modifiers + modifiers_count) {
		if (is_negative)
		    negative.insert(modifiers_mask[distance(modifiers, result)]);
		else
		    positive.insert(modifiers_mask[distance(modifiers, result)]);
	    }
#if DEBUG
	    else
		printf("(%s) is not valid modifier!\n", str.substr(start, stop - start).c_str());
#endif /* DEBUG */
	    is_negative = false;
	    start = stop;
	}
	else
	    if (str[start] == '!')
		is_negative = true;
	start++;
    }
}

/* from blackbox/src/Screen.cc */
static const char *
getFontElement(const char *pattern, char *buf, int bufsiz, ...) {
  const char *p, *v;
  char *p2;
  va_list va;

  va_start(va, bufsiz);
  buf[bufsiz-1] = 0;
  buf[bufsiz-2] = '*';
  while((v = va_arg(va, char *)) != NULL) {
    p = strcasestr(pattern, v);
    if (p) {
      strncpy(buf, p+1, bufsiz-2);
      p2 = strchr(buf, '-');
      if (p2) *p2=0;
      va_end(va);
      return p;
    }
  }
  va_end(va);
  strncpy(buf, "*", bufsiz);
  return NULL;
}

static const char *
getFontSize(const char *pattern, int *size) {
  const char *p;
  const char *p2=NULL;
  int n=0;

  for (p=pattern; 1; p++) {
    if (!*p) {
      if (p2!=NULL && n>1 && n<72) {
        *size = n; return p2+1;
      } else {
        *size = 16; return NULL;
      }
    } else if (*p=='-') {
      if (n>1 && n<72 && p2!=NULL) {
        *size = n;
        return p2+1;
      }
      p2=p; n=0;
    } else if (*p>='0' && *p<='9' && p2!=NULL) {
      n *= 10;
      n += *p-'0';
    } else {
      p2=NULL; n=0;
    }
  }
}

XFontSet
Resource::createFontSet(const string &fontname) {
  XFontSet fs;
  char **missing, *def = "-";
  int nmissing, pixel_size = 0, buf_size = 0;
  char weight[FONT_ELEMENT_SIZE], slant[FONT_ELEMENT_SIZE];

  fs = XCreateFontSet(bbtool->getXDisplay(),
                      fontname.c_str(), &missing, &nmissing, &def);
  if (fs && (! nmissing))
    return fs;

  const char *nfontname = fontname.c_str();
#ifdef    HAVE_SETLOCALE
  if (! fs) {
    if (nmissing) XFreeStringList(missing);

    setlocale(LC_CTYPE, "C");
    fs = XCreateFontSet(bbtool->getXDisplay(), fontname.c_str(),
                        &missing, &nmissing, &def);
    setlocale(LC_CTYPE, "");
  }
#endif // HAVE_SETLOCALE

  if (fs) {
    XFontStruct **fontstructs;
    char **fontnames;
    XFontsOfFontSet(fs, &fontstructs, &fontnames);
    nfontname = fontnames[0];
  }

  getFontElement(nfontname, weight, FONT_ELEMENT_SIZE,
                 "-medium-", "-bold-", "-demibold-", "-regular-", NULL);
  getFontElement(nfontname, slant, FONT_ELEMENT_SIZE,
                 "-r-", "-i-", "-o-", "-ri-", "-ro-", NULL);
  getFontSize(nfontname, &pixel_size);

  if (! strcmp(weight, "*"))
    strncpy(weight, "medium", FONT_ELEMENT_SIZE);
  if (! strcmp(slant, "*"))
    strncpy(slant, "r", FONT_ELEMENT_SIZE);
  if (pixel_size < 3)
    pixel_size = 3;
  else if (pixel_size > 97)
    pixel_size = 97;

  buf_size = strlen(nfontname) + (FONT_ELEMENT_SIZE * 2) + 64;
  char *pattern2 = new char[buf_size];
  sprintf(pattern2,
           "%s,"
           "-*-*-%s-%s-*-*-%d-*-*-*-*-*-*-*,"
           "-*-*-*-*-*-*-%d-*-*-*-*-*-*-*,*",
           nfontname, weight, slant, pixel_size, pixel_size);
  nfontname = pattern2;

  if (nmissing)
    XFreeStringList(missing);
  if (fs)
    XFreeFontSet(bbtool->getXDisplay(), fs);

  fs = XCreateFontSet(bbtool->getXDisplay(), nfontname, &missing,
                      &nmissing, &def);

  delete [] pattern2;

  return fs;
}


syntax highlighted by Code2HTML, v. 0.9.1