#!/usr/pkg/bin/perl -w
#
# 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
#

#-----------------------------------------------------------------------------
#     Copyright 2000, Olivier Chapuis
#-----------------------------------------------------------------------------

use strict;
use Getopt::Long;

my $version = '0.7.0';
my $fvwmVersion = '2.7.0';

my $prefix = $ENV{'prefix'} || '/usr/pkg';
my $ROOT_PREFIX = $ENV{'ROOT_PREFIX'} || '';
$ROOT_PREFIX = $ENV{'DESTDIR'} if $ENV{'DESTDIR'};
my $datadir = "${prefix}/share";

my $userHome = $ENV{'HOME'} || "./.";
my $userDir = $ENV{'FVWM_USERDIR'} || "$userHome/.fvwm";
my $currentThemeName = 'current';
my $themesSubDir = 'themes';
my $currentThemeSubDir = "$themesSubDir/$currentThemeName";
my $personalDirName = 'personal';
my $localeDir = "/usr/pkg/share/fvwm2/locale";

my $scriptName = ($0 =~ m:([^/]+)$:, $1);
my $path = "";
my $command_ls  = 0;
my $lsOptions = "";
my $type = "";
my $item = -1;
my $checkExec = "";
# globalfeel com loop
my $globalFeel = 0;
my $comName = "script";
my $comPid = 0;
# in line doc and script msg
my $inLineDoc = "";
my $lineLength = 70;
my $getMsg = "";
my $lang = "";
# font selector
my $fontOpt = 0;
my $fontFilter = "";
my $fontReset = 0;
my $fontIndex = 0;
my $fontCurrent = "";
my $fontStart = 0;
my $fontOnlyAdjustable = 0;
my $fontInfo = 0;

GetOptions(
#	"help"               => \&showHelp,
#	"version"            => \&showVersion,
	"dirs=s"             => \$path,
	"ls"                 => \$command_ls,
	"ls-opt=s"           => \$lsOptions,
	"type:s"             => \$type,
	"item=i"             => \$item,
	"check-exec=s"       => \$checkExec,
	"globalfeel"         => \$globalFeel,
	"com-name=s"         => \$comName,
	"in-line-doc=s"      => \$inLineDoc,
	"line-length=i"      => \$lineLength,
	"get-msg=s"          => \$getMsg,
	"lang=s"             => \$lang,
	"font"               => \$fontOpt,
	"font-filter:s"      => \$fontFilter,
	"font-reset"         => \$fontReset,
	"font-index=s"       => \$fontIndex,
	"font-current=s"     => \$fontCurrent,
	"font-start"         => \$fontStart,
	"font-info"          => \$fontInfo,
); # || wrongUsage();


if ($globalFeel) {
	$comPid = $comName;
	$comPid =~ s/script-//;
	$comPid = 0 if ($comPid !~ /^\d+$/);
	globalFeelComLoop()
	# we never return here
}
elsif ($command_ls) {
	print
		getDirListing($path, $lsOptions, $item, $type eq "dir", $type eq "file");
}
elsif ($checkExec ne "") {
	my $r = checkExecInPath($checkExec);
	print "$r\n";
}
elsif ($inLineDoc ne "") {
	buildDoc();
}
elsif ($getMsg ne "") {
	buildMsg();
}
elsif ($fontOpt) {
	buildFontLists();
}
elsif ($fontInfo) {
	buildFontInfo();
}
# ----------------------------------------------------------------------------

sub loadFile ($) {
 	my $fileName = shift;

	open(FILE, "<$fileName") || die("Can't open $fileName: [$!]\n");
	my $fileContent = join("", <FILE>);
	close(FILE) || die("Can't close $fileName: [$!]\n");
	return \$fileContent;
}

#----------------------------------------------------------------------------
# For FvwmScript-FontSelector

sub buildFontLists {
	my $return = "";
	my $list;
	my $fontList = [ ];
	my $filterLists = { };
	my $foudryFromIndex = "";
	my $familyFromIndex = "";
	my $i = 0;
	my $j;
	my $prev = "";
	my $ffFilter = "-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*";
	my @filterList = qw(* * * * * * * * * * * * * *);
	my @keys = qw (Weight Slant Width Style PixSize PtSize XRes YRes Spacing 
		AvgWidth Charset);
	my @allKeys = qw(Foundry Family);
	my @filterKeys = qw(Foundry Weight Slant Style PixSize PtSize Width XRes YRes Spacing AvgWidth Charset);
	push @allKeys, @keys;
	my $key;
	my %current;
	my %real;
	my $realFont = "";
	my @s;
	my $adjustable = 0;
	my $ffHasChanged = 0;
	my $tmpFilter = "";
	my $ffHasNoMatch = 0;

	$fontCurrent = "-misc-fixed-*-*-*-*-*-*-*-*-*-*-*-*-*" 
		if $fontCurrent eq "";
	$ffFilter = "-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*";

	fontInit($fontList, \$fontFilter, $filterLists);

	@s = split('-',$fontCurrent);
	$current{'Foundry'} = $s[1];
	$current{'Family'} = $s[2];
	$current{'Weight'} = $s[3];
	$current{'Slant'} = $s[4];
	$current{'Width'} = $s[5];
	$current{'Style'} = $s[6];
	$current{'PixSize'} = $s[7];
	$current{'PtSize'} = $s[8];
	$current{'XRes'} = $s[9];
	$current{'YRes'} = $s[10];
	$current{'Spacing'} = $s[11];
	$current{'AvgWidth'} = $s[12];
	$current{'Charset'} = $s[13] . "-" .$s[14];
	
	$ffFilter = 
		"-$current{'Foundry'}-$current{'Family'}-*-*-*-*-*-*-*-*-*-*-*-*";

	if ($fontIndex != 0) {
		if (defined $fontList->[$fontIndex-1] && 
				$fontList->[$fontIndex-1] =~ /^(.+) \((.+)\)$/) {
			$ffFilter = "-$2-$1-*-*-*-*-*-*-*-*-*-*-*-*";
			$current{'Foundry'} = $2;
			$current{'Family'} = $1;
		} else {
			$ffHasNoMatch = 1;
		}
	}

	# Merge the filter
	my @trueFontFilter = split('-',$fontFilter);

	for($i = 1; $i < 14; $i++) {
		$current{"$allKeys[$i-1]"} = $trueFontFilter[$i] 
			if $trueFontFilter[$i] ne '*';
		$current{"$allKeys[$i-1]"} .= '-' . $trueFontFilter[14] 
			if ($i == 13 && $trueFontFilter[$i] ne '*')
	}

	%real = %current;
	my @f2 = split('-',$ffFilter);
	my @f3 = split('-',$fontCurrent);
	$ffHasChanged = 1 if $current{'Foundry'} ne $f3[1] 
		|| $current{'Family'} ne $f3[2];
	for($i = 0; $i < 15; $i++) {
		my $f = "*";
		$f = $trueFontFilter[$i] if $trueFontFilter[$i] ne '*';
		$f = $f2[$i] if $f2[$i] ne '*';
		$f = $f3[$i] if $f3[$i] ne '*' && $i > 2;
		$filterList[$i] = $f;
	}

	if ($type =~ /^font-list/) {
		my $tmp = 0;
		my $ff = "$current{'Family'} ($current{'Foundry'})";
		for($i = 0; defined $fontList->[$i] && $tmp == 0; $i++) {
			$tmp = $i+1
				if $fontList->[$i] eq $ff;
		}
		#$ffHasNoMatch = 1 if ($tmp == 0);
		$tmp = "0" x (3 - length($tmp)) . $tmp;
		$return .= $tmp;
		foreach (@$fontList) { $return .=  $_ . "|" }
		if ($return eq $tmp) {
			$return .= "||No fonts match the filter|"
		}
		$return =~ s/\|$/!/;
		# return also the filter:
		for($i = 1; $i < 14; $i++) {
			$return .= $trueFontFilter[$i];
			$return .= "-" . $trueFontFilter[14] if ($i == 13);
		  	$return .= "!";
		}
	}

	if ($type =~ /all-list/) {
		my $k;

		# check consitency if foundry and/or family have changed:
		if ($ffHasChanged) {
			# remove: Spacing Width Slant Weight Charset if font is not found ...
			my @prefKeys = qw(11 5 4 3 13);
			# the size is computed later
			$filterList[7] = '*';
			$j = 0;
			my $notdone = 1;
			while ($notdone) {
				$tmpFilter = "";	
				for ($k = 1; $k < 15; $k++) {
					$tmpFilter .= '-' . $filterList[$k]; 
				}
				open(XLS,"xlsfonts -fn '$tmpFilter' 2>/dev/null |") || 
		 			($return = "Impossible to open xlsfont\n");
				while(<XLS> && $notdone) { $notdone = 0 }
				close(XLS);
				if ($notdone) {
					$filterList[$prefKeys[$j]] = '*' 
						if $trueFontFilter[$prefKeys[$j]] eq '*'; 
					if ($j == 4 && $trueFontFilter[$prefKeys[$j]] eq '*') {
								$filterList[13] = '*';
								$filterList[14] = '*';
					}
				}
				$j++;
				$notdone = 0 if $j == 5;
			}
		}

		# see if we are ajustable (what follows seems false but this work, I do
		# not know really why :o)
		$tmpFilter = "";
		for ($k = 1; $k < 7; $k++) {
			$tmpFilter .= '-' . $filterList[$k];
		}
		$tmpFilter .= '-0-0-0-0';
		for ($k = 12; $k < 15; $k++) {
			$tmpFilter .= '-' . $filterList[$k];
		}
		open(XLS,"xlsfonts -fn '$tmpFilter' 2>/dev/null |") || 
		 	($return = "Impossible to open xlsfont\n");
		while(<XLS> && $adjustable !=2) { $adjustable = 2 }
		close(XLS);
	
		# now build the lists
		$j = 3;
		foreach $key (@keys) {
			$i = 0;
			$k = 0;
			$tmpFilter = "";
			if ($adjustable == 2 && $fontOnlyAdjustable) {
				for ($k = 1; $k < 7; $k++) {
					if ($k == $j) { $tmpFilter .= '-*'; } 		
					else { $tmpFilter .= '-' . $filterList[$k]; }
				}
				$tmpFilter .= '-0-0-0-0';
				for ($k = 12; $k < 15; $k++) {
					$tmpFilter .= '-' . $filterList[$k];
				}
		 	} else {
				for ($k = 1; $k < 15; $k++) {
					if ($k == $j && $trueFontFilter[$k] eq '*') { 
						$tmpFilter .= '-*'; 
						if ($key eq "Charset") {
							$tmpFilter .= '-*'; 
							$k++;
						}
					}
					else { $tmpFilter .= '-' . $filterList[$k] }
				}
			}
			open(XLS,"xlsfonts -fn '$tmpFilter'|") || 
				($return = "Impossible to open xlsfont\n");
		
			$i = 0;
			while(<XLS>) {
				chomp;
				@s = split('-',$_);
				$list->[$i]->{"$key"} = $s[$j];
				$list->[$i]->{"$key"} .= "-" . $s[$j+1] if $key eq "Charset";
				$i++;
			}
			close(XLS);
			$j++;
		}

		# now build return
		$j = 3;
		foreach $key (@keys) {
			my @l = ();

			#needed if filter gives no font
			if ($key eq "Charset") {
				unshift @l, "$trueFontFilter[$j]-$trueFontFilter[$j+1]" 
					if $trueFontFilter[$j] ne '*';
			} else {
				unshift @l, $trueFontFilter[$j] if $trueFontFilter[$j] ne '*';
			}

			if ($adjustable == 2 && $key eq "PixSize") {
				@l = qw(4 5 6 7 8 9 10 11 12 13 14 15 16 18 20 22 24 26 28 30 
						  34 40 50 60)
			}
			for($i = 0; defined $list->[$i]->{"$key"}; $i++) {
				push @l, $list->[$i]->{"$key"}
			}
			if ($key =~ /Size$/ || $key =~ /Res$/ || $key =~ /^AvgWidth$/) {
				@l = sort {$a <=> $b} @l;
			}
			else {
				@l = sort @l;
			}

			my @newl = ();
			$prev = "";
			foreach (@l) {
				next if $_ eq '0';
				push @newl, $_ if $_ ne $prev;
				$prev = $_;
			}

			if ($key eq "Charset") {
				unshift @newl, '*-*' if $trueFontFilter[$j] eq '*';
			} else {
				unshift @newl, '*' if $trueFontFilter[$j] eq '*';
			}

			# now adjust the index and compute the real font:
			$i = 0;
			my $index = 0;
			my $diff = 1000;
			my $memDiff;
			foreach ($i = 0; defined $newl[$i]; $i++) {
				$index = $i+1 if $newl[$i] eq $current{"$key"};
				if ($key eq "PixSize" && $newl[$i] ne '*' &&
					 $current{"$key"} ne '*' &&
					 $diff > abs($newl[$i] - $current{"$key"})) {
					$index = $i+1;
					$real{"$key"} =  $newl[$i];
					$diff =  abs($newl[$i] - $current{"$key"});
				}
			}
			if ($index eq "0") {
				$index = "01";
				$real{"$key"} =  $newl[0];
			}
			$index = "0" . $index if length($index) == 1;

			$return .= $index;
 
			foreach (@newl) {
				$return .= $_ . "|";
			}
			$return =~ s/\|$/!/;
			$j++;
		}
		$i = 0;
		foreach (@allKeys) { 
			$i++;
			if ($trueFontFilter[$i] eq '*') { 
				$realFont .= $real{"$_"} . "!" 
			} else {
				$realFont .= $trueFontFilter[$i];
				if ($i == 13) {
					$realFont .= "-" . $trueFontFilter[$i+1];
					$i++;
				}
				$realFont .= "!";
			}
		}
		$return .= $realFont;
		$return .= $adjustable . "!";
		$return .= $ffHasNoMatch . "!";
	}

	if ($type =~ /filter-list/) {
		$j = 1;
		foreach $key (@filterKeys) {
			my @l = @{$filterLists->{"$key"}};
			my $index = 0;
			foreach ($i = 0; defined $l[$i]; $i++) {
				$index = $i+1 if ($l[$i] eq $trueFontFilter[$j] ||
					$l[$i] eq "$trueFontFilter[13]-$trueFontFilter[14]");
			}
			if ($index eq "0") {
				$index = "01";
			}
			$index = "0" . $index if length($index) == 1;

			$return .= $index;
 
			foreach (@l) {
				$return .= $_ . "|";
			}
			$return =~ s/\|$/!/;
			if ($j == 1) { $j=3; }
			else { $j++; }
		}
		# add dummy stuff:
		$return .= "!misc!fixed!*!*!*!*!*!*!*!*!*!*!*-*!0!0!";
		
	}
	
	#print STDERR $return . "\n";
	print $return;
	exit 0;
}

# ---------------------------------------

sub fontInit {
	my $fontList = shift;
	my $fontFilter = shift;
	my $filterLists = shift;
  
	my $str = "";
	my $oldFontFilter = "";
	my $file = "$userDir/.FvwmScript-FontSelector";
	my @filterKeys = qw(Foundry Weight Slant Style PixSize PtSize Width XRes YRes Spacing AvgWidth Charset);
	#my @filterKeys = qw(Foundry Family Weight Slant Width XRes YRes Spacing Charset);
	if (! -f $file || $fontReset) {
		#print STDERR "create RC\n";
		$$fontFilter = $oldFontFilter = "-*-*-*-*-*-*-*-*-*-*-*-*-*-*";
		my $list = myXlsfonts("$$fontFilter");
		my $prev = "";
		my $i;
	  	for($i = 0; defined $list->[$i]; $i++) {
			my $a = $list->[$i]->{'Family'};
			my $b = $list->[$i]->{'Foundry'};
			my $newFont = $a . " (" . $b . ")";
			push @$fontList, $newFont if $newFont ne $prev;
			$prev = $newFont;
		}
		@$fontList = sort @$fontList;
		my $key;
		foreach $key (@filterKeys) {
			my @l = ();
			my @newl = ();
			for($i = 0; defined $list->[$i]->{"$key"}; $i++) {
				push @l, $list->[$i]->{"$key"}
			}
			if ($key =~ /Size$/ || $key =~ /Res$/ || $key =~ /^AvgWidth$/) {
				@l = sort {$a <=> $b} @l;
			}
			else {
				@l = sort @l;
			}
			foreach (@l) {
				next if $_ eq '0' || $_ eq '';
				push @newl, $_ if $_ ne $prev;
				$prev = $_;
			}
			if ($key eq "Charset") {
				unshift @newl, '*-*';
			} else {
				unshift @newl, '*';
			}
			$i = 0;
			foreach (@newl) {
				$filterLists->{"$key"}->[$i] =  $_;
				$i++;
			}
		}
		$str = "";
		$str .= "filter=-*-*-*-*-*-*-*-*-*-*-*-*-*-*\n";
		foreach(@$fontList) { $str .= "$_\n"; }
		my $hash;
		foreach $hash (@filterKeys) {
			$str .= "hash=$hash\n";
			for($i=0; defined $filterLists->{"$hash"}->[$i];$i++) {
				$str .= $filterLists->{"$hash"}->[$i] ."\n";
			}
		}
	} else {
		#print STDERR "load RC\n";
		my $c = loadFile($file);
		my @f = split(/\n/,$$c);
		my $hash = "";
		my $i;
		foreach(@f) {
			next if /^\s*\#/;
			if (/^filter=(.+)$/) {
				$oldFontFilter = $1;
				next;
			} elsif (/^hash=(.+)$/) {
				last if ! $type =~ /filter/;
				$hash = $1;
				$i = 0;
				next;
			} elsif ($hash eq "") {
				push @$fontList, $_;
				next;
			} else {
				$filterLists->{"$hash"}->[$i] = $_;
				$i++;
			}
		}
	}
	
	$$fontFilter = $oldFontFilter if ($$fontFilter eq "");

	if ($oldFontFilter ne $$fontFilter) {
		#print STDERR "Re create RC\n";
		@$fontList = ();
		my $list = myXlsfonts("$$fontFilter");
		my $prev = "";
		my $i;
	  	for($i = 0; defined $list->[$i]; $i++) {
			my $a = $list->[$i]->{'Family'};
			my $b = $list->[$i]->{'Foundry'};
			my $newFont = $a . " (" . $b . ")";
			push @$fontList, $newFont if $newFont ne $prev;
			$prev = $newFont;
		}
		@$fontList = sort @$fontList;
		$str = "";
		$str .= "filter=$$fontFilter\n";
		foreach(@$fontList) { $str .= "$_\n"; }
		my $hash;
		foreach $hash (@filterKeys) {
			$str .= "hash=$hash\n";
			for($i=0; defined $filterLists->{"$hash"}->[$i];$i++) {
				$str .= $filterLists->{"$hash"}->[$i] ."\n";
			}
		}
	}

	if ($str ne "") { saveToFile($str,$file); }

}
#-----------------------------------------

sub myXlsfonts {
	my $filter = shift;
	my $list;
	my $i = 0;
	my @s;

	open(XLS,"xlsfonts -fn '$filter'|") || 
		die "Impossible to open xlsfont\n";

	while(<XLS>) {
		chomp;
		@s = split('-',$_);
		$list->[$i]->{'Foundry'} = $s[1];
		$list->[$i]->{'Family'} = $s[2];
		$list->[$i]->{'Weight'} = $s[3];
		$list->[$i]->{'Slant'} = $s[4];
		$list->[$i]->{'Width'} = $s[5];
		$list->[$i]->{'Style'} = $s[6];
		$list->[$i]->{'PixSize'} = $s[7];
		$list->[$i]->{'PtSize'} = $s[8];
		$list->[$i]->{'XRes'} = $s[9];
		$list->[$i]->{'YRes'} = $s[10];
		$list->[$i]->{'Spacing'} = $s[11];
		$list->[$i]->{'AvgWidth'} = $s[12];
		$list->[$i]->{'Charset'} = $s[13] . "-" .$s[14];
		$i++;
	}
	close(XLS);

	return $list;
}

# -------------------

sub buildFontInfo {
	my $return .= "";
	my $obtained = "";

	open(XLS,"xlsfonts -fn '$fontCurrent'|") || 
				($return = "Impossible to open xlsfont\n");
	while(<XLS>) { chomp; $obtained = $_ if $obtained eq ""; } 
	close(XLS);
	open(XLS,"xlsfonts -ll -fn '$obtained'|") || 
				($return = "Impossible to open xlsfont\n");
	my $count = 1;
	my $a;
	while(<XLS>) { 
		chomp;
		next if !(/^\s*name.+/ || /^\s*[A-Z].+/ || /^\s*$/); 
		s/^\s*//;
		s/\s{1}/ /g; 
		$return .= $_ . "|" if $count;
		$count = 0 if /^$/; 
	}
	close(XLS);
	$return =~ s/\|$//;
	print $return . "\n";
}

#----------------------------------------------------------------------------
# build MSG for scripts

sub buildMsg {

	$lang = $ENV{'LANG'} if $lang eq "" && $ENV{'LANG'};
	my $msgExt = "msg";
	#$lang = "en";
	#$lang = "ru";
	my $return = "";
	my $file = "";
	$lang = substr($lang, 0, 2);
	# check if ja is ok:
	if ($lang eq "ja") {
		my $lc_ctype = $ENV{'LC_CTYPE'} || "";
		$lang = "en"
		  if (!(system("fvwm-config --supports-multibyte") == 0 &&
				  $lc_ctype =~ /ja/));
	}
	if ($getMsg =~ /^\//) {
		$file = $getMsg;
	}
	else {
		$file = "$localeDir/$lang/$getMsg.$msgExt" if ($lang ne "");
		$file = "$localeDir/en/$getMsg.$msgExt" if (! -f $file);
	}
	if (! -f $file) {
		my $file = "$getMsg.$msgExt";
		print STDERR "[fvwm-themes]: Cannot find localized or default $file\n";
		print "END         0003end\n";
		exit 0;
	}

	open(MSG, $file) || die "Cannot open the msg for $getMsg: [$!]\n";

	while(<MSG>) {
		chomp;
		if (/([A-Za-z0-9]+)\s+\{(.*)\}\s*/) {
			my $id = $1;
			my $msg= $2;
			my $l1 = length($id);
			my $l2 = length($msg) - 1;
			my $l3 = length($l2);
			# illegal line!
			next if $l1 > 12;
			$id = $id . " " x (12 - $l1);
			next if $l2 > 9999;
			$l2 = "0" x (4-$l3) . $l2;
			$return .= $id . $l2 . $msg;
		}
	}
	print $return . "END         0003end\n";
	close(MSG);
	exit 0;
}

#----------------------------------------------------------------------------
# build the doc for FvwmScript-Help

# very simple HTML text parser, could be library function
# don't show this code to Mozilla, lynx or w3c developers
sub parseHtml {
	my $html = shift;
	my $lineLen = shift;

	return "" if $lineLen <= 0;

	# constants
	my $blockIndentLen = 2;  # probably 3 or 4 is better
	my $ulPrefix = "* ";
	my $olPrefix = "0. ";
	my $headerData = [  # <h1> .. <h6>
		# [ $isCentered, $dashChar ]
		[ 1, "-" ],
		[ 1, "=" ],
		[ 0, "-" ],
		[ 0, "=" ],
		[ 0, "." ],
		[ 0, undef ],
	];

	# we don't support tag parameters for now, skip them
	$html =~ s/<(\w+)(\s+\w+(\s*=\s*([^>\s]*|"[^"]+?"))?)\s*>/<$1>/sg;

	#" convert all whitespaces (currently <pre> is not supported)
	$html =~ s/\s+/ /sg;

	# title may be supported later, so this function may return [title, body]
	$html =~ s{
		<(title|javascript|style)> .*? </(title|javascript|style)> \040*
	}{
		""
	}sigxe;

	$html =~ s{
		# be sgml compliant about comments :-)
		( < [^>]+? ) -- .+? -- ( [^>]+ > )
	}{
		"$1$2"
	}sigxe;

	# skip non-html tags
	$html =~ s/<[!?].*?> *//sg;

	# support emphasis; how about *bold* and _underline_?
	$html =~ s{
		<em> (.*?) </em>
	}{
		qq("$1")
	}sigxe;

	$html =~ s{
		<blockquote> \040* (.*?) </blockquote> \040*
	}{
		my $txt = "\n" . parseHtml($1, $lineLen - $blockIndentLen);
		$txt =~ s/\n/"\n" . (" " x $blockIndentLen)/sge;
		"\n$txt\n";
	}sigxe;

	$html =~ s{
		<h([1-6])> \040* (.*?) </h\d> \040*
	}{
		my ($isCentered, $dashChar) = @{$headerData->[$1 - 1]};
		my $headLine = $2;
		my $dashLine = "";
		$dashLine = ($dashChar x length($headLine)) . "\n" if defined $dashChar;
		if ($isCentered) {
			my $identLen = int(($lineLen - length($headLine)) / 2);
			$identLen = 0 if $identLen < 0;
			$headLine = (" " x $identLen) . $headLine;
			$dashLine = (" " x $identLen) . $dashLine if $dashLine ne "";
		}
		"\n\n$headLine\n$dashLine\n"
	}sigxe;

	# supporting a bad html is not guaranteed (<li> without <ul>)
	my $listLevel = 0;
	my $listItemPrefixes = [ ];

	# handle tags
	$html =~ s{
		<(/?\w*)> \040*
	}{
		if ($1 eq "p") { "\n\n" }
		elsif ($1 eq "br") { "\n" }
		elsif ($1 eq "ul") { $listItemPrefixes->[$listLevel++] = $ulPrefix; "\n" }
		elsif ($1 eq "/ul") { $listLevel-- if $listLevel > 0; "\n\n" }
		elsif ($1 eq "ol") { $listItemPrefixes->[$listLevel++] = $olPrefix; "\n" }
		elsif ($1 eq "/ul") { $listLevel-- if $listLevel > 0; "\n\n" }
		elsif ($1 eq "li") {
			my $ident = " " x ($listLevel * $blockIndentLen);
			if ($listItemPrefixes->[$listLevel - 1] =~ /^(\d+)(.*)$/) {
				$listItemPrefixes->[$listLevel - 1] = ($1 + 1) . $2;
			}
			my $prefix = $listItemPrefixes->[$listLevel - 1];
			"\n$ident$prefix"
		}
		else { "" }
	}sigxe;

	# don't support more than 2 new-lines
	$html =~ s/\n{3,}/\n\n/sg;
	$html =~ s/^\n{2,}/\n/s;

	# split long lines to shorter ones
	$html =~ s{^(.*)$}{
		my $line = $1;
		my $formatted = "";
		my $totalLen;
		while (($totalLen = length($line)) > $lineLen) {
			my $i = $lineLen;
			while ($i >= 0 && substr($line, $i, 1) ne " ") { $i-- }
			$i = $lineLen if $i < 0;  # give up, split a word
			$formatted .= substr($line, 0, $i) . "\n";
			$line = substr($line, $i, $totalLen);
			$line =~ s/^\s+//;
		}
		"$formatted$line"
	}mge;

	return $html;
}

sub buildDoc {
	$lang = $ENV{'LANG'} if $lang eq "";
	$lang = substr($lang, 0, 2);
	my $fileExt = "html";
	# migo: actually, I think that in a proper system, "fixed" alias already
	# points to localized font, but this may be good to support any --lang.
	# This info may be read from locale/LANG/fonts.cfg probably.
	my %fixedFont = (
		'en' => "-*-fixed-medium-r-semicondensed-*-13-*",
		'ru' => "-cronyx-fixed-medium-r-semicondensed--*-*-*-*-*-*-koi8-*",
	);
	my $fontLang = exists $fixedFont{$lang}? $lang: 'en';

	my $file;
	if ($inLineDoc =~ /^\//) {
		$file = $inLineDoc;
	} else {
		$file = "$localeDir/$lang/$inLineDoc.$fileExt";
		if (! -f $file) {
			$file = "$localeDir/en/$inLineDoc.$fileExt" unless -f $file;
			$fontLang = "en";
		}
	}

	if (! -f $file) {
		print "|Documentation is not found...\n";
		exit(0);
	}

	print $fixedFont{"$fontLang"} . "|";

	my $contentRef = loadFile($file);
	my $parsedText = parseHtml($$contentRef, $lineLength);

	print join("|", split("\n", $parsedText)) . "\n";
	exit(0);
}

# this function should be removed later
sub old_buildDoc {

	$lang = $ENV{'LANG'} if $lang eq "";
	my $txtExt = "txt";
	#$lang = "en";
	#$lang = "ru";
	my $doc = "";
	my $file = "";
	$lang = substr($lang,0,2);
	if ($inLineDoc =~ /^\//) {
		$file = $inLineDoc;
	}
	else {
		$file = "$localeDir/$lang/$inLineDoc.$txtExt";
		$file = "$localeDir/C/$inLineDoc.$txtExt" if (! -f $file);
		$file = "$localeDir/en/$inLineDoc.$txtExt" if (! -f $file);
	}
	if (! -f $file) {
		print "Documentation in progress ...";
		exit 0;
	}
	#$doc = `fmt -w $lineLength $file`;
	#$doc =~ s/\n/|/g;
	#print $doc;
	open(DOC,"$file") || die "cannot open the doc for $inLineDoc";
	my $l = 0;
	my $inVerb = 0;
	my $previousWasBlanc = 0;

	while(<DOC>) {
		next if /^\#/;
		chomp;
		my $line = $_;

		if ($line =~ /^<verb>/) {
			$inVerb = 1;
			$doc .= "|" if $doc !~ /\|$/ || $previousWasBlanc;
			next;
		}
		if ($line =~ /^<\/verb>/) {
			$inVerb = 0;
			$previousWasBlanc = 1;
			next;
		}
		if ($inVerb) {
			$doc .= $line . "|";
			next;
		}

		next if ($line =~ /^<abstract>/ || $line =~ /^<\/abstract>/);

		if ($line =~ /^<title>/ || $line =~ /^<sec>/)  {
			my $type = "t";
			$type = "s" if $line =~ /^<sec>/;
			$line =~ s/^<title>\s*//;
			$line =~ s/^<sec>\s*//;
			$line =~ s/\s+$//;
			$l = length($line);
			my $t = 0;
			if ($type eq "t") {
				$t = int (($lineLength - $l) / 2);
				$t = 0 if $t <= -1;
			}
			$doc .= "|" if $doc !~ /\|$/ || $previousWasBlanc;
			$doc .= " "x$t . $line . "|" . " "x$t . "-"x$l ."|";
			$l = 0;
			$previousWasBlanc = 1;
			next;
		}

		if ($line =~ /^\s*$/) {
			$l = 0;
			if ($doc !~ /\|$/) {
				$doc .= "|";
			}
			$doc .= "|" if ($previousWasBlanc);
			$previousWasBlanc = 1;
			next;
		}

		$previousWasBlanc = 0;
	  	$line =~ s/\s+$//;
		#my $space = substr($line,0,index($line," ")+1);
		$line =~ s/^\s+//;
		my $cl = length($line);
		if ($cl + $l <= $lineLength) {
  		$doc .= " " if $doc !~ /\|$/;
			$doc .= $line;
			$l = $cl + $l;
			next;
		}
		my @larray = split(" ",$line);
		
		foreach (@larray) {
			my $wl = length($_);
			if ($wl + $l + 1 <= $lineLength) {
				$doc .= " " if $doc !~ /\|$/;
				$doc .= $_;
				$l = $wl + $l + 1
			} else {
				$doc .= "|$_";
				$l = $wl;
			}
		}
	}
	close(DOC);
	#$doc =~ s/\|/\n/g;
	print $doc . "\n";

	exit 0;	
	
}

#----------------------------------------------------------------------------

sub getDirListing {
	my ($path, $lsOptions, $index, $dirsOnly, $filesOnly) = @_;

	if ($path eq "PATH") { $path = $ENV{'PATH'} || '/bin'; }
	my @dirList = grep { $_ && -d $_ } split(':', $path);
	return "No such directory:|$path\n" unless @dirList;

	my @dirs = ();
	my @files = ();
	my $dir;
	foreach $dir (@dirList) {
		open(LSPROC, "ls $lsOptions '$dir' |");  # pipe implies ls -1
		while (<LSPROC>) {
			chomp;
			my $test = $_;
			$test =~ s/[@*\/=|]$// if $lsOptions =~ /F|--classify/;
			#s/[@*\/=|]$// if $lsOptions =~ /F|--classify/ && $index > 0;
			if (-d "$dir/$test") { push @dirs, $_; }
			else { push @files, $_; }
		}
		close(LSPROC);
	}

	if (@dirList) { @dirs = sort(@dirs); @files = sort(@files); }
	my @items = ($dirsOnly? @dirs: $filesOnly? @files: (@dirs, @files));

	$items[$index - 1] =~ s/[@*\/=|]$// 
		if $lsOptions =~ /F|--classify/ && $index > 0;

	return ($index > 0? $items[$index - 1]: join("|", @items)) . "\n";
}


sub checkExecInPath {
	my($app) = @_;
	my @pathDirs = split(':',$ENV{PATH});
	my $dir ="";
	foreach $dir (@pathDirs) {
		if ( -x "$dir/$app" ) { return 1 }
	}
	return 0;
}

#----------------------------------------------------------------------------
#
# the global feel com loop
#
#----------------------------------------------------------------------------

sub globalFeelComLoop {
	my $outFifo = ".tmp-com-out-" . $comName;
	my $inFifo = ".tmp-com-in-"  . $comName;
	my $lockFifo = ".tmp-com-lock-" . $comName;
	my $command = "";
	my $return = "";

	my @components = ("globalfeel");

	# "files" and "script" config
	my $lastBuild = "";
	my $lastHardRead = "";
	my $lastComp = "";
	my $saveState = { };
	my $hardRead = { };

	# "themes" config init
	my $personalThemes = [ ];
	$personalThemes->[0] = "personal";
	my $themesConfig = { };
	my $currentConfig = { };
	my $optConfig = { };

	# set up default
	foreach (@components) {
		$saveState->{$_}->{'file'} = "$userDir/$themesSubDir/personal/$_";
		$saveState->{$_}->{'theme'} = "personal";
		$hardRead->{$_} = "";
		$currentConfig->{$_} = "default";
	}

	# get "themes" config
	getThemesConfig($personalThemes,$themesConfig,$currentConfig,
		$optConfig,$hardRead);
	my $tmp;
	foreach $tmp (@components) {
		foreach (@$personalThemes) {
			if (defined $currentConfig->{$tmp} && $currentConfig->{$tmp} eq $_) {
				$saveState->{$tmp}->{'file'} = "$userDir/$themesSubDir/$_/$tmp";
				$saveState->{$tmp}->{'theme'} = "$_";
			}
		}
	}

	# X info:
	my	($redMask,$greenMask,$blueMask) = getXdpyInfo();
	# persistante fvwm Config:
	my $internalConfig = { };

	chdir($userDir) || die "No FvwmConfigHome $userDir";
	unlink($lockFifo);
	unlink($inFifo);
	myMakeFifo($lockFifo);

	while(1) {

		eval {
			local $SIG{ALRM} = \&checkScript;
			alarm(10);
			# block until com want to communicate
			open(LOCK,">$lockFifo") || die "cannot write fifo $lockFifo";
			alarm(0);
			close(LOCK);
		};
		if ($@ =~ /^cannot/) {
			print STDERR "$comName: cannot write fifo $lockFifo\n";
			unlink("$lockFifo");
			exit(1);
		}
		if ($@ =~ /^NoScript/) {
			print STDERR "$comName: No more FvwmScript-ConfigCenter: exit!\n";
			unlink("$lockFifo");
			exit(0);
		}
		if ($@ =~ /^Script/) {
			next;
		}
		# read the command.
		eval {
			local $SIG{ALRM} = sub { die "Timeout" };
			alarm(10);
			# block unless com is ready to write on $outFifo
			open(IN,"$outFifo") || die "cannot open $outFifo";
			alarm(0);
			($command)=(<IN>);
			close(IN);
		};
		if ($@ =~ /^cannot/) {
			print STDERR "$comName: cannot read fifo $outFifo\n";
			unlink($lockFifo);
			exit(1);
		}
		if ($@ =~ /^Timeout/) {
			print STDERR "$comName: com give an unvalide unlock!\n";
			next;
		}
		#print STDERR "msg com 2\n";
		#------------------------------------------------------------------------
		# build the answer
		chomp($command);
		my $return = "";
		#-----------------------------------
		if ($command eq "get-perso-themes") {
			foreach (@$personalThemes) {
				$return .= "$_|";
			}
			$return =~ s/\|$//;
		}
		#-----------------------------------
		elsif ($command =~ /^get-themes-info\s+(.+)$/) {
			my $comp = $1;
			$return .= "$saveState->{$comp}->{'theme'}\n";
			$return .= "$currentConfig->{$comp}\n";
			my $compCfg = $themesConfig->{$comp};
			my $themesList = "";
			my $k;
			foreach $k (sort keys %$compCfg) {
				$themesList .= "$k|";
			}
			$themesList =~ s/\|$//;
			$return .= "$themesList\n";
			my $options = $optConfig->{$comp};
			my $opt;
			if (ref($options) eq 'ARRAY') {
				foreach $opt (@$options) {
					$return .= "$opt->{'current'}\n";
				}
			}
		}
		#--------------------------------------------------------
		elsif ($command =~ /^get-config\s+(.+)\s+(.+)\s+(.+)$/) {
			my $theme = $1;
			my $comp = $2;
			my $whichPart = $3;
			my @list = ();
			if ($comp eq "All") {
				@list = @components;
				$whichPart = "All";
			} else {
				@list = ("$comp");
			}
			my $ct;
			foreach $ct (@list) {
				my $t = "";
				my $themeshash = $themesConfig->{$ct};
				if ($theme eq "current") {
					$t = $currentConfig->{$ct};
				}
				elsif ($theme =~ /^\d+$/) {
					my $i = 1;
					foreach (sort keys %$themeshash) {
						$t = $_  if $i == $theme;
						$i++;
					}
				}
				else { $t = $theme; }
				my $file;
				$file = $themeshash->{$t}->{'file'};
				if (defined $file && -f $file) {
					my $parseFunc = "parse_" . $ct . "_Config";
					my $configForScript = { };
					my $keys = [ ];
					#print STDERR "$file, $theme, $ct\n";
					my $error = eval {
						no strict 'refs';
						$parseFunc->($file,$configForScript,$keys,
							$internalConfig,$optConfig->{$ct});
					};
					$error = "Internal: $@" if $@;
					$return .= "$error\n";
					foreach (@$keys) {
				 		$return .= "$configForScript->{$_}" 
							if $_ eq $whichPart || $whichPart eq "All";
					}
				}
				else {
					$return = "config file for $ct\@$t not found!";
				}
				$return .= "\n"; 
			}
		}
		#-------------------------------------------------------------
		elsif ($command eq "get-preferences") {
			$return = get_globalfeel_Preferences();
		}
		#-------------------------------------------------------------
		elsif ($command =~ /^save-try-config\s+([A-Za-z0-9]+)\s+([A-Za-z0-9]+)\s+(\d)\s+(.+)$/) {
			my $comp = $1;
			my $whichPart = $2;
			my $configFromScript = $4;
			my $how = $3; # 0: check, 1: try, 2:save, 3: try and save
			my $buildFunc = "build_" . $comp . "_Config";
			my $fvwmConfig = { };
			my $error = { };
			my $keys = [ ];
			eval {
				no strict 'refs';
				$buildFunc->($configFromScript,$fvwmConfig,$error,$keys);
			};
			my $err = $@ ? "Internal: $@|" : "";
			$err .= "$error->{All}|"
				if defined $error->{'All'} && $error->{'All'} ne "";
			foreach (@$keys) {
				$err .= "$error->{$_}|"
					if defined $error->{$_} && $error->{$_} ne "" && 
						($_ eq $whichPart || $whichPart eq "All");
			}
			$err =~ s/\|$//;
			$err = "ok" if $err eq "";
			$lastHardRead = $hardRead->{$comp};
			$lastComp = $comp;
			$lastBuild = "";
			foreach (@$keys) {
				$lastBuild .= "$fvwmConfig->{$_}";
			}
			$lastHardRead = $hardRead->{$comp}; 
			if ($how == 0) {
				$return = $err;
			}
			if ($how == 1 || $how == 3) {
				$return = $lastBuild;
			}
			if ($how == 2 || $how == 3) {
				saveToFile($lastBuild,$saveState->{$comp}->{'file'});
				my $theme = $saveState->{$lastComp}->{'theme'};
				system("fvwm-themes-config --load $lastComp\@$theme &");
			}
			
		}
		#---------------------------------------------------
		elsif ($command =~ /^save-try-last-build\s+(\d)$/) {
			my $how = $1;
			if ($how == 1 || $how == 3) {
				$return = $lastBuild . $lastHardRead;
			}
			if ($how == 2 || $how == 3) {
				saveToFile($lastBuild,$saveState->{$lastComp}->{'file'});
				my $theme = $saveState->{$lastComp}->{'theme'};
				system("fvwm-themes-config --load $lastComp\@$theme &");
			}
		}
		# ---------------------------------------------------
		elsif ($command =~ /^set-save-file\s+(.+)\s+(\d+)$/) {
			my $comp = $1;
			my $i = $2;
			$return = $personalThemes->[$i-1];
			$saveState->{$comp}->{'file'} = 
				"$userDir/$themesSubDir/$return/$comp";
			$saveState->{$comp}->{'theme'} = $return; 
		}
		# ---------------------------------------------------
		elsif ($command =~ /^hexcolor-2-value\s+\#([a-fA-F0-9][a-fA-F0-9])([a-fA-F0-9][a-fA-F0-9])([a-fA-F0-9][a-fA-F0-9])$/) {
			my $r = hex($1);
			my $g = hex($2);
			my $b = hex($3);
			if ($redMask*$greenMask*$blueMask != 0) {
				$b = int( $b * ($blueMask+1) / 256);
				$g = $g * ( (1+($greenMask/($blueMask+1))) / 256 );
				$g = int($g) * ($blueMask + 1);
				#$r = int( $r * $redMask / 255 );
				$r = $r * ( (1+($redMask/($greenMask+$blueMask+1)))  / 256 );
				$r = int($r) * ($greenMask + $blueMask + 1);
				$return = $r + $g +$b;
				$return = 1 if $return == 0;
			}
		}
		# ---------------------------------------------------
		elsif ($command =~ /^value-2-hexcolor\s+(.*)$/) {
			my $d = $1;
			
			$return = 0;
			if ($d =~ /^\d+/ && $redMask*$greenMask*$blueMask != 0) {
				my ($r,$g,$b) = (0, 0, 0);
				$r = int ( $d / ($greenMask + $blueMask + 1));
				$d = $d - $r * ($greenMask + $blueMask + 1);
				$r = int( $r*255 / ($redMask/($greenMask + $blueMask + 1)) );
				$g = int ( $d / ($blueMask + 1));
				$d = $d - $g * ($blueMask + 1);
				$g =  int ( $g*255 / ($greenMask/($blueMask + 1)) );
				$b = int ( $d*255 / $blueMask );
				$r = 255 if $r > 255;
				$g = 255 if $g > 255;
				$b = 255 if $b > 255;
				$return = "#". int2hex($r) . int2hex($g) . int2hex($b);
			}
		}
		# --------------------------
		elsif ($command =~ /^save-preferences\s+(\d+)(\d+)(\d+)$/) {
			my $pref = "TryIsGlobal=$1\nDefaultIsGlobal=$2\nSaveIsGlobal=$3\n";
			saveToFile($pref,"$userDir/.FvwmScript-GlobalFeel");
		}
		# --------------------------
		elsif ($command eq "exit") {
			unlink($lockFifo);
			exit(0);
		}
		else {
			print STDERR "$comName: unknown command $command\n";
			$return = "0";
		}
		#------------------------------------------------------------------------
		# answer
		myMakeFifo($inFifo);
		eval {
			local $SIG{ALRM} = sub { die "Timeout" };
			alarm(10);
			# this line block until com take the answer
			open(OUT,">$inFifo") || die "cannot write fifo $inFifo";
			alarm(0);
			print OUT "ok\n" . $return;
			close(OUT);
			unlink($inFifo);
		};
		if ($@ =~ /cannot/) {
			print STDERR "$comName: cannot write on fifo $inFifo\n";
			unlink($lockFifo);
			unlink($inFifo);
			exit(1);
		}
		if ($@ =~ /Timeout/) {
			print STDERR "$comName: com do not read my answer!\n";
		}
	}
}

#----------------------------------------------------------------------------
# An alarm handler (called from eval block):
sub checkScript {

	die "Script" unless ($comPid);

	my $test = 0;
	my $lockFifo = ".tmp-com-lock-" . $comName;

	$test = 1 if kill 0 => $comPid;

	if ($test) { die "Script"; }
	else { unlink($lockFifo) if -p "$lockFifo"; die "NoScript"; }
}

#-----------------------------------------------------------------------------
# 
sub myMakeFifo {
	my ($fifo) = @_;
	system("mkfifo '$fifo'");  # not portable: mknod '$fifo' p
}

#-----------------------------------------------------------------------------
# For killing FvwmScript-ConfigCenter if an error happen in this script!
END {
	if ($globalFeel) {
		if ($?) {
			my $lockFifo = ".tmp-com-lock-" . $comName;
			my $inFifo = ".tmp-com-in-" . $comName;
			my $message = "fvwm-themes-script: internal error $?\n";
			# actually $@ is never defined in END
			$message .= "\teval error: $@\n" if $@;
			$message .= "\tOS error: $!\n" if $!;
			# actually the following is never executed on unix
			$message .= "\tOS error 2: $^E\n" if $^E && !($! && $^E eq $!);

			unlink($lockFifo) if -p "$lockFifo";
			unlink($inFifo) if -p "$lockFifo";
		  	if ($comPid) {
				kill(9, $comPid);
				$message .= "\tkilling FvwmScript-ConfigCenter";
			}
			print STDERR "$message\n";
		}
	}
}

# -----------------------------------------------------------------------------
# get the themes info from fvwm-themes-config

sub getThemesConfig {
	my $personalThemes = shift;
	my $themesConfig = shift;
	my $currentConfig = shift;
	my $optConfig = shift;
	my $hardRead = shift;

	my $in = `fvwm-themes-config --config-center`;
	chomp($in);
	my @input = split(/\n/, $in);
	my $i = 0;
	my $j = 0;
	my $k = 1;
	my $comp = "";
	my $theme = "";
	my $inHardRead = 1;
	my $inOptions = 0;
	my $o = 0;
	while(defined $input[$i]) {
		if ($input[$i] =~ /^configuration of (.+) for the Config Center$/) {
			$comp = $1;
			$j = 0;
			$i++;
			next
		}
		if ($inHardRead) {
			if ($input[$i] =~ /END/) { $inHardRead = 0 }
			else { $hardRead->{'globalfeel'} .= "$input[$i]\n" }
			$i++;
			next
		}
		if ($input[$i] =~ /^OPTIONS/) {
			$inOptions = 1;
			$i++;
			$o = 0;
			next;
		}
		if ($inOptions) {
			if ($input[$i] =~ /^END/) { $inOptions = 0 }
			else { 
				my ($tmp1,$tmp2) = split (":",$input[$i]);
				$optConfig->{$comp}->[$o]->{'file'} = $tmp1;
				$optConfig->{$comp}->[$o]->{'current'} = $tmp2;
				$o++;
			}
			$i++;
			next;
		}
		if ($comp eq "") {
			if ($input[$i] ne "personal") {
				$personalThemes->[$k] = $input[$i];
				$k++;
			}
			$i++;
			next
		}
		if ($j == 0) {
			$currentConfig->{$comp} = $input[$i];
			$j++; $i++;
			next
		}
		elsif ($j == 1) {
			$theme = $input[$i];
			$j=2; $i++;
			next
		}
		elsif ($j == 2) {
			$themesConfig->{$comp}->{$theme}->{'file'} = "$input[$i]";
			$j=1; $i++;
			next
		}
		$i++;
	}
}

#----------------------------------------------------------------------------
# get the globalfeel preferences

sub get_globalfeel_Preferences {
	my $file = "$userDir/.FvwmScript-GlobalFeel";

	return "000" if (! -f $file);

	my $tryIsGlobal = 0;
	my $defaultIsGlobal = 0;
	my $saveIsGlobal = 0;

	open(FILE,"$file");
	while(<FILE>) {
		if ($_ =~ /^TryIsGlobal=(\d+)$/) {
			$tryIsGlobal = $1;
		}
		elsif ($_ =~ /^DefaultIsGlobal=(\d+)$/) {
			$defaultIsGlobal = $1;
		}
		elsif ($_ =~ /^SaveIsGlobal=(\d+)$/) {
			$saveIsGlobal = $1;
		}
	}
	close(FILE);
	return "$tryIsGlobal$defaultIsGlobal$saveIsGlobal";
}

#----------------------------------------------------------------------------
# build globalfeel from a sequence

sub  build_globalfeel_Config {
	my $configFromScript = shift;
	my $fvwmConfig = shift;
	my $err = shift;
	my $keys = shift;
	my $index = 0;
	my @list = ();
	my ($tmp,$tmp2,$hide,$x,$y);
	my $impossible = "An Impossible error happen, GASP!";

	@$keys = ("Focus", "Move", "Paging", "Transient", "Hints");

	# check for the good number of "!"
	my @test = split(/!/,$configFromScript);
	if ($#test != 12) {
		$err->{'All'} = 
			"Why do you enter a ! in a field where you have to enter numbers? ($#test)|";
	}

	# -------------------------------------------- Focus
	$fvwmConfig->{'Focus'} .= 
		"\n# -------------------------- Focus and Placement ".
		"--------------------------\n\n";
	$tmp = substr($configFromScript,$index,1);
	if ($tmp == 1) { $fvwmConfig->{'Focus'} .= "Style * ClickToFocus" }
	elsif ($tmp == 2) { $fvwmConfig->{'Focus'} .= "Style * MouseFocus" }
	elsif ($tmp == 3) { $fvwmConfig->{'Focus'} .= "Style * SloppyFocus" }
	else { $err->{'Focus'} .= "$impossible|" }
	#
	$index++;
	$tmp = substr($configFromScript,$index,1);
	if ($tmp == 1) { $fvwmConfig->{'Focus'} .= ", ClickToFocusPassesClick" }
	elsif ($tmp == 0) { $fvwmConfig->{'Focus'} .= ", ClickToFocusPassesClickOff"}
	else { $err->{'Focus'} .= "$impossible|" }
	#
	$index++;
	$tmp = substr($configFromScript,$index,1);
	if ($tmp == 1) {
		$fvwmConfig->{'Focus'} .= ", ClickToFocusRaises, MouseFocusClickRaises"
	} 
	elsif ($tmp == 0) {
		$fvwmConfig->{'Focus'} .= 
			", ClickToFocusRaisesOff, MouseFocusClickRaisesOff"
	}
	else { $err->{'Focus'} .= "$impossible|" }
	$fvwmConfig->{'Focus'} .= "\n";
	#
	$index++;
	$tmp = substr($configFromScript,$index,1);
	if ($tmp == 1) { $fvwmConfig->{'Focus'} .= "ColormapFocus FollowsFocus\n" }
	elsif ($tmp == 0) { $fvwmConfig->{'Focus'} .= "ColormapFocus FollowsMouse\n"}
	else { $err->{'Focus'} .= "$impossible|" }
	# 
	$index++;
	$tmp = substr($configFromScript,$index,1);
	if ($tmp == 1) {
		$fvwmConfig->{'Focus'} .= 
			"Style * TileCascadePlacement"
	}
	elsif ($tmp == 2) {
		$fvwmConfig->{'Focus'} .= 
			"Style * TileManualPlacement"
	}
	elsif ($tmp == 3) {
		$fvwmConfig->{'Focus'} .= 
			"Style * MinOverlapPlacement"
	}
	elsif ($tmp == 4) {
		$fvwmConfig->{'Focus'} .= 
			"Style * MinOverlapPercentPlacement"
	}
	elsif ($tmp == 5) {
		$fvwmConfig->{'Focus'} .= 
			"Style * ManualPlacement"
	}
	elsif ($tmp == 6) {
		$fvwmConfig->{'Focus'} .= 
			"Style * CascadePlacement"
	}
	else { $err->{'Focus'} .= "$impossible|" }
	#
	$index++;
	$tmp = substr($configFromScript,$index,1);
	if ($tmp == 1) { $fvwmConfig->{'Focus'} .= ", GrabFocus" }
	elsif ($tmp == 0) { $fvwmConfig->{'Focus'} .= ", GrabFocusOff" }
	else { $err->{'Focus'} .= "$impossible|" }
	#
	$index++;
	$tmp = substr($configFromScript,$index,1);
	if ($tmp == 1) { $fvwmConfig->{'Focus'} .= ", UsePPosition" }
	elsif ($tmp == 0) { $fvwmConfig->{'Focus'} .= ", NoPPosition" }
	else { $err->{'Focus'} .= "$impossible|" }
	$fvwmConfig->{'Focus'} .= "\n";

	# ----------------------------------------------- Move
	$fvwmConfig->{'Move'} .= 
		"\n# ---------------------------- Move and Resize ".
		"----------------------------\n\n";
	$index++;
	$tmp = substr($configFromScript,$index,1);
	if ($tmp == 0) { $fvwmConfig->{'Move'} .= "Style * ResizeOpaque\n" } 
	elsif ($tmp == 1) { $fvwmConfig->{'Move'} .= "Style * ResizeOutLine\n" } 
	else { $err->{'Move'} .= "$impossible|" }
	#
	$index++;
	$tmp = substr($configFromScript,$index,index($configFromScript,"!")-$index);
	$index += length($tmp)+1;
	$configFromScript = substr($configFromScript,$index);
	$index = 0;
	if ($tmp =~ /^\d+$/) { $fvwmConfig->{'Move'} .= "OpaqueMoveSize $tmp\n" } 
	else {
		$err->{'Move'} = "Percentage for opaque move size must be an integer|";
		return $err;
	}
	#
	$tmp = substr($configFromScript,$index,1);
	if ($tmp == 0) { $fvwmConfig->{'Move'} .= "Emulate MWM\n" } 
	elsif ($tmp == 1) { $fvwmConfig->{'Move'} .= "Emulate FVWM\n" } 
	else { $err->{'Move'} .= "$impossible|" }
	#
	$index++;
	$tmp = substr($configFromScript,$index,1);
	$hide = 0;
	if ($tmp == 1) { $hide = 1 } 
	elsif ($tmp == 0) {}
	else { $err->{'Move'} .= "$impossible|" }
	#
	$index++;
	$tmp = substr($configFromScript,$index,1);
	if ($tmp == 1) { $hide = ($hide) ? 3 : 2 } 
	elsif ($tmp == 0) {}
	else { $err->{'Move'} .= "$impossible|" }
	if ($hide == 0) {$fvwmConfig->{'Move'} .= "HideGeometryWindow Never\n" }
	elsif ($hide == 1) {$fvwmConfig->{'Move'} .= "HideGeometryWindow Resize\n" }
	elsif ($hide == 2) {$fvwmConfig->{'Move'} .= "HideGeometryWindow Move\n" }
	else { $fvwmConfig->{'Move'} .= "HideGeometryWindow\n" }
	#
	$index++;
	$tmp = substr($configFromScript,$index,1);
	if ($tmp == 0) {
		$fvwmConfig->{'Move'} .= "BugOpts FlickeringMoveWorkaround Off\n"
	}
	elsif ($tmp == 1) {
		$fvwmConfig->{'Move'} .= "BugOpts FlickeringMoveWorkaround On\n"
	}
	else { $err->{'Move'} .= "$impossible|" }
	#
	$index++;
	$tmp = substr($configFromScript,$index,index($configFromScript,"!")-$index);
	$index += length($tmp)+1;
	$configFromScript = substr($configFromScript,$index);
	$index = 0;
	$tmp = 0 if $tmp eq "";
	if ($tmp =~ /^\d+$/) { $fvwmConfig->{'Move'} .= "SnapAttraction $tmp " } 
	else {
		$err->{'Move'} = "Distance for snap attraction must be an integer >= 0|";
	}
	#
	$tmp = substr($configFromScript,$index,1);
	if ($tmp == 1 || $tmp == 5) { $fvwmConfig->{'Move'} .= "All" }
	elsif ($tmp == 2 || $tmp == 6) { $fvwmConfig->{'Move'} .= "SameType" }
	elsif ($tmp == 3 || $tmp == 7) { $fvwmConfig->{'Move'} .= "Windows" }
	elsif ($tmp == 4 || $tmp == 8) { $fvwmConfig->{'Move'} .= "Icons" }
	else { $err->{'Move'} .= "$impossible" }
	if ($tmp >= 5) { $fvwmConfig->{'Move'} .= " Screen" }
	$fvwmConfig->{'Move'} .= "\n";
	#
	$index++;
	$tmp = substr($configFromScript,$index,index($configFromScript,"!")-$index);
	$index += length($tmp)+1;
	$configFromScript = substr($configFromScript,$index);
	$index = 0;
	$tmp = 0 if $tmp eq "";
	if ($tmp =~ /^\d+$/) { $fvwmConfig->{'Move'} .= "SnapGrid $tmp " }
	else {
		$err->{'Move'} .= "X attraction grid coordinate must be an integer >= 0|";
	}
	#
	$tmp = substr($configFromScript,$index,index($configFromScript,"!")-$index);
	$index += length($tmp)+1;
	$configFromScript = substr($configFromScript,$index);
	$index = 0;
	$tmp = 0 if $tmp eq "";
	if ($tmp =~ /^\d+$/) { $fvwmConfig->{'Move'} .= "$tmp" }
	else {
		$err->{'Move'} .= "Y attraction grid coordinate must be an integer >= 0|";
	}
	$fvwmConfig->{'Move'} .= "\n";
	#
	$tmp = substr($configFromScript,$index,1);
	if ($tmp == 0) { $fvwmConfig->{'Move'} .= "XorValue " } 
	elsif ($tmp == 1) { $fvwmConfig->{'Move'} .= "XorPixmap " } 
	else { $err->{'Move'} .= "$impossible|" }
	#
	$index++;
	$tmp = substr($configFromScript,$index,index($configFromScript,"!")-$index);
	$index += length($tmp)+1;
	$configFromScript = substr($configFromScript,$index);
	$index = 0;
	$fvwmConfig->{'Move'} .= "$tmp\n";

	# ------------------------------------------ Paging
	$fvwmConfig->{'Paging'} .= 
		"\n# ---------------------- Paging and Mouse Parameters ".
		"----------------------\n\n";
	$tmp = substr($configFromScript,$index,1);
	$index++;
	$tmp2 = substr($configFromScript,$index,1);
	$tmp2 = ($tmp2) ? 1000 : 1;
	$x = 0;
	if ($tmp == 0) { $x = 0 }
	elsif ($tmp == 1) { $x = 100 * $tmp2 }
	elsif ($tmp == 2) { $x = 90 * $tmp2 }
	elsif ($tmp == 3) { $x = 75 * $tmp2 }
	elsif ($tmp == 4) { $x = 66 * $tmp2 }
	elsif ($tmp == 5) { $x = 50 * $tmp2 }
	elsif ($tmp == 6) { $x = 33 * $tmp2 }
	elsif ($tmp == 7) { $x = 25 * $tmp2 }
	elsif ($tmp == 8) { $x = 10 * $tmp2 }
	elsif ($tmp == 9) { $x = 5 * $tmp2 }
	else { $err->{'Paging'} .= "$impossible|" }
	#
	$index++;
	$tmp = substr($configFromScript,$index,1);
	$index++;
	$tmp2 = substr($configFromScript,$index,1);
	$tmp2 = ($tmp2) ? 1000 : 1;
	$y = 0;
	if ($tmp == 0) { $y = 0 }
	elsif ($tmp == 1) { $y = 100 * $tmp2 }
	elsif ($tmp == 2) { $y = 90 * $tmp2 }
	elsif ($tmp == 3) { $y = 75 * $tmp2 }
	elsif ($tmp == 4) { $y = 66 * $tmp2 }
	elsif ($tmp == 5) { $y = 50 * $tmp2 }
	elsif ($tmp == 6) { $y = 33 * $tmp2 }
	elsif ($tmp == 7) { $y = 25 * $tmp2 }
	elsif ($tmp == 8) { $y = 10 * $tmp2 }
	elsif ($tmp == 9) { $y = 5 * $tmp2 }
	else { $err->{'Paging'} .= "$impossible|" }
	$fvwmConfig->{'Paging'} .= "EdgeScroll $x $y\n";
	#
	$index++;
	$tmp = substr($configFromScript,$index,index($configFromScript,"!")-$index);
	$index += length($tmp)+1;
	$configFromScript = substr($configFromScript,$index);
	$index = 0;
	$tmp = 0 if $tmp eq "";
	if ($tmp =~ /^\d+$/) { $x = "$tmp " }
	else { $err->{'Paging'} = "Paging delay must be an integer >= 0|" }
	#
	$tmp = substr($configFromScript,$index,index($configFromScript,"!")-$index);
	$index += length($tmp)+1;
	$configFromScript = substr($configFromScript,$index);
	$index = 0;
	$tmp = 0 if $tmp eq "";
	if ($tmp =~ /^\d+$/) { $y = "$tmp " }
	else { $err->{'Paging'} = "Moving resistance must be an integer >= 0|" }
	$fvwmConfig->{'Paging'} .= "EdgeResistance $x $y\n";
	#
	$tmp = substr($configFromScript,$index,1);
	if ($tmp == 1) { $fvwmConfig->{'Paging'} .= "EdgeThickness 1\n" }
	elsif ($tmp == 2) { $fvwmConfig->{'Paging'} .= "EdgeThickness 1\n" }
	else { $err->{'Paging'} .= "$impossible|" }
	#
	$index++;
	$tmp = substr($configFromScript,$index,index($configFromScript,"!")-$index);
	$index += length($tmp)+1;
	$configFromScript = substr($configFromScript,$index);
	$index = 0;
	$tmp = 150 if $tmp eq "";
	if ($tmp =~ /^\d+$/) { $fvwmConfig->{'Paging'} .= "ClickTime $tmp\n" }
	else { $err->{'Paging'} = "Double Click time must be an integer >= 0|" }
	#
	$tmp = substr($configFromScript,$index,index($configFromScript,"!")-$index);
	$index += length($tmp)+1;
	$configFromScript = substr($configFromScript,$index);
	$index = 0;
	$tmp = 3 if $tmp eq "";
	if ($tmp =~ /^\d+$/) { $fvwmConfig->{'Paging'} .= "MoveThreshold $tmp\n" }
	else { $err->{'Paging'} = "Move Threshold must be an integer >= 0|" }

	# ----------------------------------------------- Transient
	$fvwmConfig->{'Transient'} .= 
		"\n# -------------------- Transient Windows and Animation ".
		"--------------------\n\n";
	$tmp = substr($configFromScript,$index,1);
	if ($tmp == 0) { 
		$fvwmConfig->{'Transient'} .= "Style * DecorateTransient" 
	} 
	elsif ($tmp == 1) { 
		$fvwmConfig->{'Transient'} .= "Style * NakedTransient" 
	} 
	else { $err->{'Transient'} .= "$impossible|" }
	#
	$index++;
	$tmp = substr($configFromScript,$index,1);
	if ($tmp == 0) { $fvwmConfig->{'Transient'} .= ", DontRaiseTransient" } 
	elsif ($tmp == 1) { $fvwmConfig->{'Transient'} .= ", RaiseTransient" }
	else { $err->{'Transient'} .= "$impossible|" }
	#
	$index++;
	$tmp = substr($configFromScript,$index,1);
	if ($tmp == 0) { $fvwmConfig->{'Transient'} .= ", DontLowerTransient" }
	elsif ($tmp == 1) { $fvwmConfig->{'Transient'} .= ", LowerTransient" }
	else { $err->{'Transient'} .= "$impossible|" }
	#
	$index++;
	$tmp = substr($configFromScript,$index,1);
	if ($tmp == 0) { $fvwmConfig->{'Transient'} .= ", DontStackTransientParent"} 
	elsif ($tmp == 1) { $fvwmConfig->{'Transient'} .= ", StackTransientParent" }
	else { $err->{'Transient'} .= "$impossible|" }
	#
	$index++;
	$tmp = substr($configFromScript,$index,1);
	if ($tmp == 0) { $fvwmConfig->{'Transient'} .= ", GrabFocusTransientOff" }
	elsif ($tmp == 1) { $fvwmConfig->{'Transient'} .= ", GrabFocusTransient" }
	else { $err->{'Transient'} .= "$impossible|" }
	$fvwmConfig->{'Transient'} .= "\n";
	#
	$index++;
	$tmp = substr($configFromScript,$index,index($configFromScript,"!")-$index);
	$index += length($tmp)+1;
	$configFromScript = substr($configFromScript,$index);
	$index = 0;
	$tmp = 20 if $tmp eq "";
	if ($tmp =~ /^\d+$/) { 
		$fvwmConfig->{'Transient'} .= "Style * WindowShadeSteps $tmp" 
	}
	else { $err->{'Transient'} = "Shade step must be an integer >= 0|" }
	#
	$tmp = substr($configFromScript,$index,1);
	if ($tmp == 1) { $fvwmConfig->{'Transient'} .= ", WindowShadeScrolls" }
	elsif ($tmp == 0) { $fvwmConfig->{'Transient'} .= ", WindowShadeShrinks" }
	else { $err->{'Transient'} .= "$impossible|" }
	$fvwmConfig->{'Transient'} .= "\n";
	#
	$index++;
	$tmp = substr($configFromScript,$index,index($configFromScript,"!")-$index);
	$index += length($tmp)+1;
	$configFromScript = substr($configFromScript,$index);
	$index = 0;
	$tmp = 10 if $tmp eq "";
	if ($tmp =~ /^\d+$/) { $fvwmConfig->{'Transient'} .= "SetAnimation  $tmp " }
	else { $err->{'Transient'} = "Animation speed must be an integer >= 0|" }
	#
	$tmp = substr($configFromScript,$index,index($configFromScript,"!")-$index);
	$index += length($tmp)+1;
	$configFromScript = substr($configFromScript,$index);
	$index = 0;
	@list = split(/\s+/,$tmp);
	$tmp2 = 1;
	foreach (@list) { $tmp2 = 0 if $_ !~ /^-?\d*\.?\d*$/ }
	if ($tmp2) { $fvwmConfig->{'Transient'} .= " $tmp" }
	else { 
		$err->{'Transient'} = 
			"Animation Steps must be a sequence of < 17 rationals around 0 to 1|"
	}
	$fvwmConfig->{'Transient'} .= "\n";

	# ----------------------------------------------- Hints
	$fvwmConfig->{'Hints'} .= 
		"\n# -------------------- Hints, Busy Cursor and Advanced ".
		"--------------------\n\n";
	$tmp = substr($configFromScript,$index,1);
	if ($tmp == 0) { $fvwmConfig->{'Hints'} .= "Style * NoDecorHint" }
	elsif ($tmp == 1) { $fvwmConfig->{'Hints'} .= "Style * MwmDecor" }
	else { $err->{'Hints'} .= "$impossible|" }
	#
	$index++;
	$tmp = substr($configFromScript,$index,1);
	if ($tmp == 0) { $fvwmConfig->{'Hints'} .= ", NoOLDecor" }
	elsif ($tmp == 1) { $fvwmConfig->{'Hints'} .= ", OLDecor" }
	else { $err->{'Hints'} .= "$impossible|" }
	#
	$index++;
	$tmp = substr($configFromScript,$index,1);
	if ($tmp == 0) { $fvwmConfig->{'Hints'} .= ", HintOverride" }
	elsif ($tmp == 1) { $fvwmConfig->{'Hints'} .= ", NoOverride" }
	else { $err->{'Hints'} .= "$impossible|" }
	#
	$index++;
	$tmp = substr($configFromScript,$index,1);
	if ($tmp == 0) { $fvwmConfig->{'Hints'} .= ", NoFuncHint" }
	elsif ($tmp == 1) { $fvwmConfig->{'Hints'} .= ", MwmFunctions" }
	else { $err->{'Hints'} .= "$impossible|" }
	#
	$index++;
	$tmp = substr($configFromScript,$index,1);
	if ($tmp == 0) { $fvwmConfig->{'Hints'} .= ", GNOMEIgnoreHints" }
	elsif ($tmp == 1) { $fvwmConfig->{'Hints'} .= ", GNOMEUseHints" }
	else { $err->{'Hints'} .= "$impossible|" }
	$fvwmConfig->{'Hints'} .= "\n";
	#
	$index++;
	$tmp = substr($configFromScript,$index,1);
	if ($tmp == 0) { $fvwmConfig->{'Hints'} .= "BugOpts ModalityIsEvil off\n" }
	elsif ($tmp == 1) { $fvwmConfig->{'Hints'} .= "BugOpts ModalityIsEvil on\n" }
	else { $err->{'Hints'} .= "$impossible|" }
	#
	$index++;
	$tmp = substr($configFromScript,$index,1);
	if ($tmp == 0) { $fvwmConfig->{'Hints'} .= "BusyCursor Read off" }
	elsif ($tmp == 1) { $fvwmConfig->{'Hints'} .= "BusyCursor Read on" }
	else { $err->{'Hints'} .= "$impossible|" }
	#
	$index++;
	# Need to be "fixed" in other places ... 
	$tmp = substr($configFromScript,$index,1);
	if ($tmp == 0) { 
		#$fvwmConfig->{'Hints'} .= ", Recapture off" 
	}
	elsif ($tmp == 1) { 
		#$fvwmConfig->{'Hints'} .= ", Recapture on"
	}
	else { $err->{'Hints'} .= "$impossible|" }
	#
	$index++;
	$tmp = substr($configFromScript,$index,1);
	if ($tmp == 0) { $fvwmConfig->{'Hints'} .= ", Wait off" }
	elsif ($tmp == 1) { $fvwmConfig->{'Hints'} .= ", Wait on" }
	else { $err->{'Hints'} .= "$impossible|" }
	#
	$index++;
	$tmp = substr($configFromScript,$index,1);
	if ($tmp == 0) { $fvwmConfig->{'Hints'} .= ", ModuleSynchronous off" }
	elsif ($tmp == 1) { $fvwmConfig->{'Hints'} .= ", ModuleSynchronous on" }
	else { $err->{'Hints'} .= "$impossible|" }
	$fvwmConfig->{'Hints'} .= "\n";
	#
	$index++;
	$tmp = substr($configFromScript,$index,1);
	if ($tmp == 1) { $fvwmConfig->{'Hints'} .= "# Automatic detection of the color limit\n" }
	elsif ($tmp == 2) { $fvwmConfig->{'Hints'} .= "ColorLimit 2\n" }
	elsif ($tmp == 3) { $fvwmConfig->{'Hints'} .= "ColorLimit 9\n" }
	elsif ($tmp == 4) { $fvwmConfig->{'Hints'} .= "ColorLimit 19\n" }
	elsif ($tmp == 5) { $fvwmConfig->{'Hints'} .= "ColorLimit 29\n" }
	elsif ($tmp == 6) { $fvwmConfig->{'Hints'} .= "ColorLimit 39\n" }
	elsif ($tmp == 7) { $fvwmConfig->{'Hints'} .= "ColorLimit 49\n" }
	elsif ($tmp == 8) { $fvwmConfig->{'Hints'} .= "ColorLimit 61\n" }
	elsif ($tmp == 9) { $fvwmConfig->{'Hints'} .= "ColorLimit 0\n" }
	else { $err->{'Hints'} .= "$impossible|" }
	#
	$index++;
	$tmp = substr($configFromScript,$index,1);
	if ($tmp == 0) { 
		$fvwmConfig->{'Hints'} .= "BugOpts MixedVisualWorkaround off\n" 
	}
	elsif ($tmp == 1) { 
		$fvwmConfig->{'Hints'} .= "BugOpts MixedVisualWorkaround on\n" 
	}
	else { $err->{'Hints'} .= "$impossible|" }
	#
	$index++;
	$tmp = substr($configFromScript,$index,1);
	if ($tmp == 0) { 
		$fvwmConfig->{'Hints'} .= "BugOpts RaiseOverNativeWindows off\n" 
	}
	elsif ($tmp == 1) { 
		$fvwmConfig->{'Hints'} .= "BugOpts RaiseOverNativeWindows on\n" 
	}
	else { $err->{'Hints'} .= "$impossible|" }
	#
	$index++;
	$tmp = substr($configFromScript,$index,1);
	if ($tmp == 0) { $fvwmConfig->{'Hints'} .= "Style * SaveUnderOff" } 
	elsif ($tmp == 1) { $fvwmConfig->{'Hints'} .= "Style * SaveUnder"} 
	else { $err->{'Hints'} .= "$impossible|" }
	#
	$index++;
	$tmp = substr($configFromScript,$index,1);
	if ($tmp == 0) { $fvwmConfig->{'Hints'} .= ", BackingStoreOff" }
	elsif ($tmp == 1) { $fvwmConfig->{'Hints'} .= ", BackingStore" }
	else { $err->{'Hints'} .= "$impossible|" }
	$fvwmConfig->{'Hints'} .= "\n";
	#
	$index++;
	$tmp = substr($configFromScript,$index,1);
	if ($tmp == 1) { $fvwmConfig->{'Hints'} .= "ModuleTimeout 2\n" }
	elsif ($tmp == 2) { $fvwmConfig->{'Hints'} .= "ModuleTimeout 5\n" }
	elsif ($tmp == 3) { $fvwmConfig->{'Hints'} .= "ModuleTimeout 7\n" }
	elsif ($tmp == 4) { $fvwmConfig->{'Hints'} .= "ModuleTimeout 10\n" }
	elsif ($tmp == 5) { $fvwmConfig->{'Hints'} .= "ModuleTimeout 15\n" }
	elsif ($tmp == 6) { $fvwmConfig->{'Hints'} .= "ModuleTimeout 30\n" }
	elsif ($tmp == 7) { $fvwmConfig->{'Hints'} .= "ModuleTimeout 45\n" }
	elsif ($tmp == 8) { $fvwmConfig->{'Hints'} .= "ModuleTimeout 60\n" }
	elsif ($tmp == 8) { $fvwmConfig->{'Hints'} .= "ModuleTimeout 120\n" }

	else { $err->{'Hints'} .= "$impossible|" }
}


#-----------------------------------------------------------------------------
# Parse globalfeel file and build a sequence "for" FvwmScript 

sub parse_globalfeel_Config {
	my $file = shift;
	my $configForScript = shift;
	my $keys = shift;

	my $config = {};
	default_globalfeel_Config($config);
	@$keys = ("Focus", "Move", "Paging", "Transient", "Hints");

	open(FILE,"$file") || return "Err: cannot open $file";
	my $multiline = "";
	my $line;
	my $oldPlacement = 0;

	while(<FILE>) {
		chomp;		
		if ( /\\$/ && ! /\\\\$/) {
			s/\\$//;
			$multiline = $multiline . $_;
			next;
	  	} else {
			$line= $multiline . $_;
			$multiline = "";
		}
		# remove starting blanc:
		$line =~ s/^\s+//;
		# removing comments
		next if $line =~ /^\#/;
		# humm ...
		$line =~ s/\s+\#.*$//;
		$line =~ s/\s+$//;

		if ($line =~ /^ColormapFocus\s+FollowsMouse/i) {
			$config->{'colormapmouse'} = 0		
		}
		elsif ($line =~ /^ColormapFocus\s+FollowsFocus/i) {
			$config->{'colormapmouse'} = 1
		}
		elsif ($line =~ /^OpaqueMoveSize/i) {
			if ($line =~ /^OpaqueMoveSize\s+(\d+)/i) {
				$config->{'OpaqueMoveSize'} = $1
			}
			else {
				$config->{'OpaqueMoveSize'} = 5
			}
		}
		elsif ($line =~ /^Emulate/i) {
			if ($line =~ /^Emulate\s+mwm/i) {
				$config->{'emulate'} = 0
			}
			else {
				$config->{'emulate'} = 1
			}
		}
		elsif ($line =~ /^HideGeometryWindow\s+(.*)/i) {
			my @opt = split $1;
			foreach (@opt) {
				s/\s//g;
				if (/^Never/i) { 
					$config->{'hidemove'} = 0; $config->{'hideresize'} = 0
				} 
				elsif (/^Move/) {  $config->{'hidemove'} = 1 }
				elsif (/^Resize/) {  $config->{'hideresize'} = 1 }
			}
		}
		elsif ($line =~ /^SnapAttraction\s+([-]*\d+)\s*(\w*)\s*(.*)/i) {
			my $type = "";
			my $screen = 0;
			$config->{'snapdistance'} = $1;
			$type = $2 if defined $2;
			$screen = 1 if defined $3 && $3 =~ /^screen/i;
			if ($type =~ /^All$/i) {
				$config->{'snapbehavior'} = 1
			}
			elsif ($type =~ /^SameType$/i) {
				$config->{'snapbehavior'} = 2
			}
			elsif ($type =~ /^Windows$/i) {
				$config->{'snapbehavior'} = 3
			}
			elsif ($type =~ /^Icons$/i) {
				$config->{'snapbehavior'} = 4
			}
			$config->{'snapbehavior'} += 4 if ($screen eq "1");
		}
		elsif ($line =~ /^SnapGrid\s+(\d+)\s+(\d+)/i) {
			$config->{'snap_X'} = $1;
			$config->{'snap_Y'} = $2;
		}
		elsif ($line =~ /^BugOpts\s+(.+)$/i) {
			my $token = $1; 
			while($token ne "") {
				my $opt = getNextToken(\$token);
				my $bool = getBoolArg(\$token);
				if ($opt =~ /^FlickeringMoveWorkaround$/i) {
					$config->{'FlickeringMoveWorkaround'} = ($bool eq "1") ? 1:0;
				}
				elsif ($opt =~ /^ModalityIsEvil$/i) {
					$config->{'ModalityIsEvil'} = ($bool eq "0") ? 0:1;
				}
				elsif ($opt =~ /^MixedVisualWorkaround$/i) {
					$config->{'MixedVisualWorkaround'} = ($bool eq "1") ? 1:0;
				}
				elsif ($opt =~ /^RaiseOverNativeWindow$/i) {
					$config->{'RaiseOverNativeWindows'} = ($bool eq "1") ? 1:0;
				}
			}
		}
		elsif ($line =~ /^xorvalue\s+(\d+)$/i) {
			$config->{'xor'}= 0;
			$config->{'xor_value'}= $1;
		}
		elsif ($line =~ /^xorpixmap\s+(.+)$/i) {
			$config->{'xor'}= 1;
			$config->{'xor_pixmap'}= $1;
		}
		elsif ($line =~ /^BusyCursor\s+(.+)$/i) {
			my $token = $1;
			while($token ne "") {
				my $opt = getNextToken(\$token);
				my $bool = getBoolArg(\$token);
				next if $bool != 0 && $bool != 1;
				if ($opt =~ /^Read$/i) {
					$config->{'Busy_Read'}=$bool;
				}
				elsif ($opt =~ /^Read$/i) {
					$config->{'Busy_Recapture'}=$bool;
				}
				elsif ($opt =~ /^Recapture$/i) {
					$config->{'Busy_Recapture'}=$bool;
				}
				elsif ($opt =~ /^Wait$/i) {
					$config->{'Busy_Wait'}=$bool;
				}
				elsif ($opt =~ /^ModuleSynchronous$/i) {
					$config->{'Busy_Module'}=$bool;
				}
			}
		}
		elsif ($line =~ /^ColorLimit\s+(\d+)/) {
			$config->{'ColorLimit'} = $1
		}
		elsif ($line =~ /^ModuleTimeout\s+(\d+)/) {
			$config->{'ModuleTimeout'} = $1
		}
		elsif ($line =~ /^EdgeScroll\s+(\d+)\s+(\d+)/) {
			$config->{'EdgeScroll_H'} = $1;
			$config->{'EdgeScroll_V'} = $2;
		}
		elsif ($line =~ /^EdgeThickness\s+(\d)/) {
			$config->{'EdgeThickness'} = 2 if $1 == 2
		}
		elsif ($line =~ /EdgeResistance\s+(\d+)\s+(\d+)/) {
			$config->{'EdgeResistance_delay'} = $1;
			$config->{'EdgeResistance_move'} = $2;
		}
		elsif ($line =~ /^ClickTime\s+(\d*)\s*$/) {
			$config->{'ClickTime'} = $1;
		}
		elsif ($line =~ /^MoveThreshold\s+(\d*)\s*$/) {
			$config->{'MoveThreshold'} = $1;
		}
		elsif ($line =~ /^SetAnimation\s*(\d*)\s*(.*)/i) {
			$config->{'SetAnimatin_speed'} = $1 if defined $1;
			$config->{'SetAnimatin_frac'} = $2 if defined $2;
		}
		elsif ($line =~ /^Style\s+["]*[*]["]*\s+(.+)$/i) {
			my $token = $1;
			while($token ne "") {
				my $style = getNextStyle(\$token);
				if ($style =~ /^ClickToFocus$/i) {
					$config->{'focus'} = 1
				} 
				elsif ($style=~/^MouseFocus$/i || $style=~/^FocusFollowsMouse$/i) {
					$config->{'focus'} = 2
				}
				elsif ($style =~ /^SloppyFocus$/i) {
					$config->{'focus'} = 3
				}
				elsif ($style =~ /^ClickToFocusPassesClick$/i) {
					$config->{'ClickToFocusPassesClick'} = 1
				}
				elsif ($style =~ /^ClickToFocusPassesClickOff$/i) {
					$config->{'ClickToFocusPassesClick'} = 0
				}
				elsif ($style =~ /^ClickToFocusRaises$/i) {
					$config->{'ClickToFocusRaises'} = 1
				}
				elsif ($style =~ /^ClickToFocusRaisesOff$/i) {
					$config->{'ClickToFocusRaises'} = 0
				}
				elsif ($style =~ /^MouseFocusClickRaisesOff$/i) {
					$config->{'MouseFocusClickRaisesOff'} = 1
				}
				elsif ($style =~ /^MouseFocusClickRaises$/i) {
					$config->{'MouseFocusClickRaisesOff'} = 0
				}
				### old placement style (style supported)
				elsif ($style =~ /^SmartPlacement$/i) {
					$oldPlacement = 1;
					$config->{'SmartPlacement'} = 1 
				}
				elsif ($style =~ /^DumbPlacement$/i) {
					$oldPlacement = 1;
					$config->{'SmartPlacement'} = 0
				}
				elsif ($style =~ /^CleverPlacementOff$/i) {
					$oldPlacement = 1;
					$config->{'CleverPlacementOff'} = 1 
				}
				elsif ($style =~ /^CleverPlacement$/i) {
					$oldPlacement = 1;
					$config->{'CleverPlacementOff'} = 0
				}
				elsif ($style =~ /^RandomPlacement$/i) {
					$oldPlacement = 1;
					$config->{'RandomPlacement'} = 1
				}
				elsif ($style =~ /^ActivePlacement$/i) {
					$oldPlacement = 1;
					$config->{'RandomPlacement'} = 0
				}
				### new placement style
				elsif ($style =~ /^TileCascadePlacement$/i) {
					$oldPlacement = 0;
					$config->{'placement'} = 1
				}
				elsif ($style =~ /^TileManualPlacement$/i) {
					$oldPlacement = 0;
					$config->{'placement'} = 2
				}
				elsif ($style =~ /^MinOverlapPlacement$/i) {
					$oldPlacement = 0;
					$config->{'placement'} = 3
				}
				elsif ($style =~ /^MinOverlapPercentPlacement$/i) {
					$config->{'placement'} = 4
				}
				elsif ($style =~ /^ManualPlacement$/i) {
					$oldPlacement = 0;
					$config->{'placement'} = 5
				}
				elsif ($style =~ /^CascadePlacement$/i) {
					$oldPlacement = 0;
					$config->{'placement'} = 6
				}
				# end of new placement style
				elsif ($style =~ /^GrabFocusOff$/i) {
					$config->{'GrabFocusOff'} = 0
				}
				elsif ($style =~ /^GrabFocus$/i) {
					$config->{'GrabFocusOff'} = 1
				}
				elsif ($style =~ /^NoPPosition$/i) {
					$config->{'NoPPosition'} = 0
				}
				elsif ($style =~ /^UsePPosition$/i) {
					$config->{'NoPPosition'} = 1
				}
				elsif ($style =~ /^ResizeOutLine$/i) {
					$config->{'ResizeOutLine'} = 1
				}
				elsif ($style =~ /^ResizeOpaque$/i) {
					$config->{'ResizeOutLine'} = 0
				}
				elsif ($style =~ /^SaveUnderOff$/i) {
					$config->{'SaveUnderOff'} = 0
				}
				elsif ($style =~ /^SaveUnder$/i) {
					$config->{'SaveUnderOff'} = 1
				}
				elsif ($style =~ /^BackingStoreOff$/i) {
					$config->{'BackinStoreOff'} = 0
				}
				elsif ($style =~ /^BackingStore$/i) {
					$config->{'BackingStoreOff'} = 1
				}
				elsif ($style =~ /^NakedTransient$/i) {
					$config->{'NakedTransient'} = 1
				}
				elsif ($style =~ /^DecorateTransient$/i) {
					$config->{'NakedTransient'} = 0
				}
				elsif ($style =~ /^DontRaiseTransient$/i) {
					$config->{'DontRaiseTransient'} = 0
				}
				elsif ($style =~ /^RaiseTransient$/i) {
					$config->{'DontRaiseTransient'} = 1
				}
				elsif ($style =~ /^DontLowerTransient$/i) {
					$config->{'DontLowerTransient'} = 0
				}
				elsif ($style =~ /^LowerTransient$/i) {
					$config->{'DontLowerTransient'} = 1
				}
				elsif ($style =~ /^DontStackTransientParent$/i) {
					$config->{'DontStackTransientParent'} = 0
				}
				elsif ($style =~ /^StackTransientParent$/i) {
					$config->{'DontStackTransientParent'} = 1
				}
				elsif ($style =~ /^GrabFocusTransientOff$/i) {
					$config->{'GrabFocusTransientOff'} = 0
				}
				elsif ($style =~ /^GrabFocusTransient$/i) {
					$config->{'GrabFocusTransientOff'} = 1
				}
				elsif ($style =~ /^WindowShadeSteps$/i) {
					if ($line = /\s*(\d+)/) { 
						$config->{'WindowShadeSteps'} = $1;
						my $dummy = getNextToken(\$token);
					}
				}
				elsif ($style =~ /^WindowShadeScrolls$/i) {
					$config->{'WindowShadeScrolls'} = 1;
				}
				elsif ($style =~ /^WindowShadeShrinks$/i) {
					$config->{'WindowShadeScrolls'} = 0;
				}
				elsif ($style =~ /^NoDecorHint$/i) {
					$config->{'NoDecorHint'} = 0;
				}
				elsif ($style =~ /^MwmDecor$/i) {
					$config->{'NoDecorHint'} = 1;
				}
				elsif ($style =~ /^NoOLDecor$/i) {
					$config->{'NoOLDecor'} = 0;
				}
				elsif ($style =~ /^OLDecor$/i) {
					$config->{'NoOLDecor'} = 1;
				}
				elsif ($style =~ /^NoOverride$/i) {
					$config->{'NoOverride'} = 1;
				}
				elsif ($style =~ /^HintOverride$/i) {
					$config->{'NoOverride'} = 0;
				}
				elsif ($style =~ /^NoFuncHint$/i) {
					$config->{'NoFuncHint'} = 0;
				}
				elsif ($style =~ /^MwmFunctions$/i) {
					$config->{'NoDecorHint'} = 1;
				}
				elsif ($style =~ /^GNOMEUseHints$/i) {
					$config->{'GNOMEUseHints'} = 1;
				}
				elsif ($style =~ /^GNOMEIgnoreHints$/i) {
					$config->{'GNOMEUseHints'} = 1;
				}
			}
		}
	}
	close(FILE);

	# compute clickraise
	if ($config->{'focus'} == 1) {
		$config->{'clickraise'} = $config->{'ClickToFocusRaises'}
	}
	else {
		$config->{'clickraise'} = $config->{'MouseFocusClickRaisesOff'} ? 0:1
	}
	# compute placement
	if ($oldPlacement) {
		if ($config->{'SmartPlacement'}) {
			if (!$config->{'RandomPlacement'}) {
				$config->{'placement'} = 2
			}
			elsif ($config->{'CleverPlacementOff'}) {
				$config->{'placement'} = 1
			}				
			else {
				$config->{'placement'} = 3
			}
		}
		elsif ($config->{'RandomPlacement'}) {
			$config->{'placement'} = 6
		}
		else {
			$config->{'placement'} = 5 
		}
	}
	# compute EdgeScroll
	my $scroll_h = int($config->{'EdgeScroll_H'}/1000);
	if ($scroll_h <= 0) { $config->{'circular_h'} = 0 }
	else { $config->{'EdgeScroll_H'} = $scroll_h; $config->{'circular_h'} = 1 }
	if ($config->{'EdgeScroll_H'} <= 0) { $config->{'edgescroll_h'} = 0 }
	elsif ($config->{'EdgeScroll_H'} <= 7) { $config->{'edgescroll_h'} = 9 }
	elsif ($config->{'EdgeScroll_H'} <= 17) { $config->{'edgescroll_h'} = 8 }
	elsif ($config->{'EdgeScroll_H'} <= 29) { $config->{'edgescroll_h'} = 7 }
	elsif ($config->{'EdgeScroll_H'} <= 41) { $config->{'edgescroll_h'} = 6 }
	elsif ($config->{'EdgeScroll_H'} <= 58) { $config->{'edgescroll_h'} = 5 }
	elsif ($config->{'EdgeScroll_H'} <= 70) { $config->{'edgescroll_h'} = 4 }
	elsif ($config->{'EdgeScroll_H'} <= 82) { $config->{'edgescroll_h'} = 3 }
	elsif ($config->{'EdgeScroll_H'} <= 95) { $config->{'edgescroll_h'} = 2 }
	else { $config->{'edgescroll_h'} = 1 }
	my $scroll_v = int($config->{'EdgeScroll_V'}/1000);
	if ($scroll_v <= 0) { $config->{'circular_v'} = 0 }
	else { $config->{'EdgeScroll_V'} = $scroll_v; $config->{'circular_v'} = 1 }
	if ($config->{'EdgeScroll_V'} <= 0) { $config->{'edgescroll_v'} = 0 }
	elsif ($config->{'EdgeScroll_V'} <= 7) { $config->{'edgescroll_v'} = 9 }
	elsif ($config->{'EdgeScroll_V'} <= 17) { $config->{'edgescroll_v'} = 8 }
	elsif ($config->{'EdgeScroll_V'} <= 29) { $config->{'edgescroll_v'} = 7 }
	elsif ($config->{'EdgeScroll_V'} <= 41) { $config->{'edgescroll_v'} = 6 }
	elsif ($config->{'EdgeScroll_V'} <= 58) { $config->{'edgescroll_v'} = 5 }
	elsif ($config->{'EdgeScroll_V'} <= 70) { $config->{'edgescroll_v'} = 4 }
	elsif ($config->{'EdgeScroll_V'} <= 82) { $config->{'edgescroll_v'} = 3 }
	elsif ($config->{'EdgeScroll_V'} <= 95) { $config->{'edgescroll_v'} = 2 }
	else { $config->{'edgescroll_v'} = 1 }
	# Compute Color Limit
	if ($config->{'ColorLimit'} < 0) { $config->{'color_limit'} = 1 }
	elsif ($config->{'ColorLimit'} == 0) { $config->{'color_limit'} = 9 }
	elsif ($config->{'ColorLimit'} <= 2) { $config->{'color_limit'} = 2 }
	elsif ($config->{'ColorLimit'} <= 14) { $config->{'color_limit'} = 3 }
	elsif ($config->{'ColorLimit'} <= 24) { $config->{'color_limit'} = 4 }
	elsif ($config->{'ColorLimit'} <= 34) { $config->{'color_limit'} = 5 }
	elsif ($config->{'ColorLimit'} <= 44) { $config->{'color_limit'} = 6 }
	elsif ($config->{'ColorLimit'} <= 54) { $config->{'color_limit'} = 7 }
	else { $config->{'color_limit'} = 8 }
	# Compute module timeout
	if ($config->{'ModuleTimeout'} <= 0) { $config->{'module_timeout'} = 6 }
	elsif ($config->{'ModuleTimeout'} <= 3) { $config->{'module_timeout'} = 1 }
	elsif ($config->{'ModuleTimeout'} <= 6) { $config->{'module_timeout'} = 2 }
	elsif ($config->{'ModuleTimeout'} <= 8) { $config->{'module_timeout'} = 3 }
	elsif ($config->{'ModuleTimeout'} <= 12) { $config->{'module_timeout'} = 4 }
	elsif ($config->{'ModuleTimeout'} <= 20) { $config->{'module_timeout'} = 5 }
	elsif ($config->{'ModuleTimeout'} <= 38) { $config->{'module_timeout'} = 6 }
	elsif ($config->{'ModuleTimeout'} <= 53) { $config->{'module_timeout'} = 7 }
	elsif ($config->{'ModuleTimeout'} <= 90) { $config->{'module_timeout'} = 8 }
	else { $config->{'module_timeout'} = 9 }

	$configForScript->{'Focus'} = $config->{'focus'} . 
		$config->{'ClickToFocusPassesClick'} . $config->{'clickraise'} . 
		$config->{'colormapmouse'} . $config->{'placement'} . 
		$config->{'GrabFocusOff'} . $config->{'NoPPosition'};
	
	$configForScript->{'Move'} = $config->{'ResizeOutLine'} . 
		$config->{'OpaqueMoveSize'} . "!" . $config->{'emulate'} . 
		$config->{'hideresize'} . $config->{'hidemove'} .
		$config->{'FlickeringMoveWorkaround'} .
		$config->{'snapdistance'} . "!" . $config->{'snapbehavior'} .
		$config->{'snap_X'} . "!" . $config->{'snap_Y'} . "!" .
		$config->{'xor'} . $config->{'xor_value'} . "!" .
		$config->{'xor_pixmap'} . "!";

	$configForScript->{'Paging'} = $config->{'edgescroll_h'} . 
		$config->{'circular_h'} . $config->{'edgescroll_v'} . 
		$config->{'circular_v'} . $config->{'EdgeResistance_delay'} ."!". 
		$config->{'EdgeResistance_move'}."!". $config->{'EdgeThickness'} . 
		$config->{'ClickTime'} ."!". $config->{'MoveThreshold'}."!";

	$configForScript->{'Transient'} = $config->{'NakedTransient'} . 
		$config->{'DontRaiseTransient'} . $config->{'DontLowerTransient'} . 
		$config->{'DontStackTransientParent'} .
		$config->{'GrabFocusTransientOff'} .
	 	$config->{'WindowShadeSteps'}. "!" . $config->{'WindowShadeScrolls'} .
		$config->{'SetAnimatin_speed'}. "!". $config->{'SetAnimatin_frac'}."!";

	$configForScript->{'Hints'} = $config->{'NoDecorHint'} . 
		$config->{'NoOLDecor'} . $config->{'NoOverride'} .
		$config->{'NoFuncHint'} . $config->{'GNOMEUseHints'} . 
		$config->{'ModalityIsEvil'} .
		$config->{'Busy_Read'} . $config->{'Busy_Recapture'} .
		$config->{'Busy_Wait'} . $config->{'Busy_Module'} .
		$config->{'color_limit'} . $config->{'MixedVisualWorkaround'} .
		$config->{'RaiseOverNativeWindow'} . $config->{'SaveUnderOff'} . 
		$config->{'BackingStoreOff'} . $config->{'module_timeout'};
	return 0
}

# ---------------------------------------------------------------------------
# "default" config (but in theory the theme/default/* is loaded 

sub default_globalfeel_Config {
	my $config = shift;

	$config->{'ClickToFocusPassesClick'} = 0;
	$config->{'ClickToFocusRaises'} = 1;
	$config->{'MouseFocusClickRaisesOff'} = 1;
	$config->{'focus'} = 0;
	$config->{'colormapmouse'} = 0;
	$config->{'SmartPlacement'} = 1;
	$config->{'RandomPlacement'} = 1;
	$config->{'CleverPlacementOff'} = 1;
	$config->{'placement'} = 0;
	$config->{'GrabFocusOff'} = 0;
	$config->{'NoPPosition'} = 0;
	$config->{'ResizeOutLine'} = 1;
	$config->{'OpaqueMoveSize'} = 5;
	$config->{'emulate'} = 1;
	$config->{'hideresize'} = 0;
	$config->{'hidemove'} = 0;
	$config->{'FlickeringMoveWorkaround'} = 0;
	$config->{'snapdistance'} = 0;
	$config->{'snapbehavior'} = 1;
	$config->{'snap_X'} = 1;
	$config->{'snap_Y'} = 1;
	$config->{'xor'} = 0; # 0 Value, 1 Pixmap
	$config->{'xor_value'} = 0; # fvwm default
	$config->{'xor_pixmap'} = "";
	$config->{'BackingStoreOff'} = 0;
	$config->{'EdgeScroll_H'} = 0;
	$config->{'EdgeScroll_V'} = 0;
	$config->{'edgescroll_h'} = 1;
	$config->{'edgescroll_v'} = 1;
	$config->{'circular_h'} = 0;
	$config->{'circilar_v'} = 0;
	$config->{'EdgeResistance_delay'} = 0;
	$config->{'EdgeResistance_move'} = 0;
	$config->{'EdgeThickness'} = 1;
	$config->{'ClickTime'} = 150;
	$config->{'MoveThreshold'} = 3;
	$config->{'NakedTransient'} = 1;
	$config->{'DontRaiseTransient'} = 0;
	$config->{'DontLowerTransient'} = 0;
	$config->{'DontStackTransientParent'} = 0;
	$config->{'GrabFocusTransientOff'} = 0;
	$config->{'WindowShadeSteps'} = 20;
	$config->{'WindowShadeScrolls'} = 1;
	$config->{'EdgeResistance_delay'} = 0;
	$config->{'EdgeResistance_move'} = 0;
	$config->{'SetAnimatin_speed'} = 10;
	$config->{'SetAnimatin_frac'} = "1 0 .01 .03 .08 .18 .3 .45 .6 .75 " .
		".85 .90 .94 .97 .99 1.0";
	$config->{'NoDecorHint'} = 1;
	$config->{'NoOLDecor'} = 1;
	$config->{'NoOverride'} = 0;
	$config->{'NoFuncHint'} = 1;
	$config->{'GNOMEUseHints'} = 1;
	$config->{'ModalityIsEvil'} = 1;
	$config->{'Busy_Read'} = 0;
	$config->{'Busy_Recapture'} = 1;
	$config->{'Busy_Wait'} = 0;
	$config->{'Busy_Module'} = 0;
	$config->{'ColorLimit'} = -1; # No color limit config command!
	$config->{'color_limit'} = 1;
	$config->{'MixedVisualWorkaround'} = 0;
	$config->{'RaiseOverNativeWindow'} = 0;
	$config->{'SaveUnderOff'} = 0;
	$config->{'BackingStoreOff'} = 0;
	$config->{'ModuleTimeout'} = 30;
	$config->{'module_timeout'} = 6;

}

# -----------------------------------------------------------------------------
# parsing func

sub getNextToken {
	my ($line) = @_;
	my $token = "";

	$$line =~ s/^\s*,\s*//;
	my $quote = " ";
	$quote = "\"" if ($$line =~ /^\"/);
	$quote = "\'" if ($$line =~ /^\'/);
	$quote = "\`" if ($$line =~ /^\`/);
	$$line =~ s/^$quote//;
	#print "$$line\n";
	if ($$line =~ /$quote/) {
		$token = substr($$line,0,index($$line,$quote));
	} else {
		$token = $$line;
	}
	$$line = substr($$line,length($token));
	$token =~ s/$quote$//;
	$token =~ s/,//g;
	return $token;
}

sub getNextStyle {
	my ($line) = @_;
	my $token = "";

	$$line =~ s/^\s*,\s*//;
	#print "$$line\n";
	if ($$line =~ /,/) {
		$token = substr($$line,0,index($$line,","));
	} else {
		$token = $$line;
	}
	$$line = substr($$line,length($token));
	$token =~ s/,//g;
	return $token;
}

sub getBoolArg {
	my ($line) = @_;
	my $t = "";
	my $l = 0;
	$$line =~ s/^\s*//;
	if ($$line =~ /^(on\s*,*\s*)/i) {
		$l = length($1);
		$t = 1
	}
	elsif  ($$line =~ /^(off\s*,*\s*)/i) {
		$l = length($1);
		$t = 0
	}
	elsif  ($$line =~ /^(yes\s*,*\s*)/i) {
		$l = length($1);
		$t = 1
	}
	elsif  ($$line =~ /^(y\s*,*\s*)/i) {
		$l = length($1);
		$t = 1
	}
	elsif  ($$line =~ /^(no\s*,*\s*)/i) {
		$l = length($1);
		$t = 0
	}
	elsif  ($$line =~ /^(n\s*,*\s*)/i) {
		$l = length($1);
		$t = 0
	}
	elsif ($$line =~ /^(True\s*,*\s*)/i) {
		$l = length($1);
		$t = 1
	}
	elsif ($$line =~ /^(T\s*,*\s*)/i) {
		$l = length($1);
		$t = 1
	}
	elsif ($$line =~ /^(False\s*,*\s*)/i) {
		$l = length($1);
		$t = 0
	}
	elsif ($$line =~ /^(False\s*,*\s*)/i) {
		$l = length($1);
		$t = 0
	}
	# hummm ...
	elsif ($$line =~ /^(toggle[,]\s*)/i) {
		$l = length($1);
		$t = -1
	}
	$$line = substr($$line,$l);
	return $t;
}

#----------------------------------------------------------------------------
#

sub saveToFile {
	my $out = shift;
	my $file = shift;

	my $dir = substr($file,0,rindex($file,"/"));
	# using decimal (not octal) 755 is incorrect; also I have umask 02, not 022
	mkdir($dir, 0777 - umask()) if (! -d $dir);

	my $date = `date +'%d-%b-%Y %T'`;
	chomp($date);
	my $user = $ENV{'USER'} || "unknown";
	my $host = $ENV{'HOSTNAME'} || "unknown";
	my $save = "# Automatically generated by FVWM-Themes $version on $date\n" .
		"# for $user\@$host\n";
	$out = $save . $out;

	open(OUT, ">$file");
	print OUT $out;
	close(OUT);
}

#----------------------------------------------------------------------------
#

sub int2hex {
	my @Hex=(0 .. 9, "a" .. "f");
	my $i= shift;
 	# modified for speed (olicha)
	my $h = $Hex[$i/16] . $Hex[$i%16];
  	return $h;
}


#----------------------------------------------------------------------------
#
sub getXdpyInfo {

	my $redMask = 0;
	my $greenMask = 0;
	my $blueMask = 0;
	my $defaultVisual = "";
	my $ok = 0;

	open(XDPY,"xdpyinfo |");
	while (<XDPY>) {
		if (/default visual id:\s+(.*)$/) {
			$defaultVisual = $1;
		}
		if (/visual id:\s+$defaultVisual$/) {
			$ok = 1;
		}
		if ($ok && /red, green, blue masks:\s+([0-9a-fA-Fx]+),\s+([0-9a-fA-Fx]+),\s+([0-9a-fA-Fx]+)$/) {
			$redMask = hex($1);
			$greenMask = hex($2);
			$blueMask = hex($3);
			$ok = 0
		}
	}
	close(XDPY);

	return ($redMask,$greenMask,$blueMask)
}
