#!/usr/bin/perl
# 
# ---------------------------------------------------------------------------
#  fvwm-menu-desktop
#  See the man page fvwm-menu-desktop.1 for instructions.
#
#  Created on 22/07/1999 by Olivier Chapuis
#
#  Updated on 15/08/1999 by Mikhael Goikhman
#
# ---------------------------------------------------------------------------
# COPYING
#
# The script is distributed by the same terms as fvwm itself.
# See GNU General Public License for details.
#
# ---------------------------------------------------------------------------
# Modification History
#
#  * migo (15/08/1999): Prepared for inclusion into fvwm. Many small fixes
#    in the script and the man page. All 'fvwm2' replaced with 'fvwm' except
#    for file names and fvwm2gnome. New --fvwm-gtk-name option.
#
#  * 13/08/1999: Rename the script and some options. Use strict. Bug fixes.
#    Add showHelp and showVersion.
#
#  * 03/08/1999: General clean up (thanks Mikhael !). Set a version number:
#    Version 0.7
#
#  * 22/07/1999: Test version
#
#----------------------------------------------------------------------------
# TODO MUST:
#    1. Correct the english of the man page (partially done).
#
# TODO:
#    1. Prevent "inconsistent" conjonctions of options (perhaps we can do
#       GetOptions with hands (in my machine I think I will win 0.15 sec).
#    2. Better default ?
#    3. Add other desktops ?? CDE ???? (need to be at work to see
#       if we can do that).
#    4. Make a general clean up II.
#
#----------------------------------------------------------------------------
# The script: Main

#--------
# Modules
use strict;
# For the option
use Getopt::Long;

# version needs to be fvwm version or script version ?
my $version = "2.3.7";

#--------
# Defaults (most of them can be modified with the options)

# paths

my $GNOME_PREFIX = '/usr';		# gnome install-dir
# Default is "gnome" since fvwm is gnome compilant and not kde compilant.
my $APPS_DIR = "$GNOME_PREFIX/share/gnome/apps";
my $GNOME_APPS = $APPS_DIR;
my $KDE_PREFIX = $ENV{KDEDIR};
my $KDE_APPS = "$KDE_PREFIX/share/applnk";
my $KDE_MINI_ICONS = "$KDE_PREFIX/share/icons/mini/";
my $KDE_ICONS = "$KDE_PREFIX/share/icons/";
my $OPT_INSTALL_PREFIX = '';

# Default for the mini-icons is mini/ (relativelly to the ImagePath)
my $MINI_ICONS_DIR = 'mini/';
# Then the default for icon is ImagePath (consistent with kde, fvwm2gnome
# and almost consistent with wm-icons)
my $ICONS_DIR = '';
# For png icons
my $PNG_ICONS = '';
# Default for mini-icons and icons translation
my $TRAN_MINI_ICONS = 'mini/';
my $TRAN_ICONS = '';

#Unused path at the present time
#$GNOME_ICONS = "$GNOME_PREFIX/share/pixmaps/";

# Name
my $MENU_TITLE = 'Gnome System Menu';  # default top title
my $MENU_NAME  = 'gnome-sys';   # default top menu name
my $MENU_TYPE  = 'fvwm';        # default menu type
my $DESKTOP    = '';            # will contain Kde or Gnome if possible
my $OPT_MENU_TITLE = '';
my $OPT_MENU_NAME  = '';
my $fvwmGtkName = "FvwmGtk";    # FvwmGtk module name

# Default "icon"

# mini-icons default (app for application, folder for folder, title for
# submenu title, toptitle for the top title, fvwm_ for fvwm menu, gtk_ for
# FvwmGtk menu) the variable $flag will be fvwm_ or gtk_. Use kde
# default icons for fvwm menus and gnome icons for gtk menus
my %DI;

$DI{fvwm_app}      = 'mini-x.xpm:dh:%::'; # micon:law:placement:unused 
$DI{fvwm_folder}   = 'folder.xpm:dh:%::'; # idem
$DI{fvwm_title}    = 'folder.xpm:dh:%::'; # micon:law:place:spic:color 
$DI{fvwm_toptitle} = 'mini-k.xpm:no:%::'; # idem
$DI{gtk_app}       = 'gnome-default.png:dh:::';	# idem
$DI{gtk_folder}    = 'gnome-folder.png:dh:::';  # micon:law:unused
$DI{gtk_title}     = 'gnome-folder.png:dh:::';  # idem
$DI{gtk_toptitle}  = 'gnome-logo-icon-transparent.png:no:::'; # idem

my @list=();
my $i='';

my %dmicon;
my %law;
my %place;
my %spic;
my %scolor;

foreach $i (keys(%DI)) {
	@list = split(':',$DI{$i});
	$dmicon{$i} = $list[0];	# "default" mini-icon
	$law{$i}    = $list[1];	# default law
	$place{$i}  = $list[2];	# default position
	$spic{$i}   = $list[3];	# sidepic icon
	$scolor{$i} = $list[4];	# color for sidpic
	$DI{$i} = '';
}

my $MINI_ICONS = 0;		# mini-icon disabled  (enable =1)
my $TRAN       = 0;		# mini-icon translation disabled (enable =1)


# default for style
my %dstyle;
$dstyle{mini_icon} = 'mini-x.xpm'; # default MiniIcons Style
$dstyle{gnome_mini_icon}  = 'gnome-default.xpm';
$dstyle{icon}      = 'x.xpm';	# default Icons Style
$dstyle{gnome_icon}       = 'gnome-default.xpm';
my $style_law   = 'dh';		# default law
my $addstyle    = '';		# a style to add every where
my $STYLE       = 0;		# style is disable (enable =1)
my $TRAN_STYLE  = 0;		# translation for style is disabled (enable =1)
my $STYLEOUTPUT = '';		# The styles are in this variable
my $ICON_STYLE  = '';


# default term for runing applications in a terminal
my $TERM_CMD = "xterm -e";


# Other stuff
my $timelimit = 10;                    # limit runing time for the script
my $LANG      = $ENV{LANG} || "";      # Internationalization support :o)
my @PATH_DIRS = split(':',$ENV{PATH}); # for checking if applications exist
my $CHECK     = 1;                     # we check by default
my $MENU_DESTROY = '';
my $DESC_DIR = '';
my $SUBMENUS_PREFIX = '';
my $IKWID = 0;

my $name = "";
my $l = ""; 
my $j = ""; 
my $tmp_icon =""; 
my $level = 0; 
my $nlevel = 0; 
my $top_level = 0;
my $cdir = ""; 
my $dir = ""; 
my @Rec_Dir_List = (); 
my @Main_List = (); 
my $flag = "";
my $order ="";
my $add = 1;

#--------
# Read the options

GetOptions(
	"help" => \&showHelp,
	"version" => \&showVersion,
	"install-prefix:s" => $OPT_INSTALL_PREFIX,
	"desktop:s" => \$MENU_NAME,
	"type:s" => \$MENU_TYPE, 
	"fvwm-gtk-name=s" => \$fvwmGtkName,
	"title:s" => \$OPT_MENU_TITLE,
	"name:s" => \$OPT_MENU_NAME,
	"enable-mini-icons" => \$MINI_ICONS,
	"enable-tran-mini-icons" => \$TRAN,
	"mini-icons-path:s" => \$MINI_ICONS_DIR,
	"png-icons-path:s"=> \$PNG_ICONS,
	"tran-mini-icons-path:s" => \$TRAN_MINI_ICONS,
	"icon-toptitle:s" => \$DI{"fvwm_toptitle"},
	"icon-title:s" => \$DI{"fvwm_title"},
	"icon-folder:s" => \$DI{"fvwm_folder"},
	"icon-app:s" => \$DI{"fvwm_app"},
	"enable-style" => \$STYLE,
	"enable-tran-style" => \$TRAN_STYLE,
	"icon-style:s" => \$ICON_STYLE,
	"icons-path:s" => \$ICONS_DIR,
	"tran-icons-path:s" => \$TRAN_ICONS,
	"submenu-name-prefix:s"  => \$SUBMENUS_PREFIX,
	"dir:s" => \$DESC_DIR,
	"destroy-type:s" => \$MENU_DESTROY,
	"xterm:s" => \$TERM_CMD,
	"lang:s" => \$LANG,
	"check-app!" => \$CHECK,
	"i-know-what-i-do" => \$IKWID,
) || wrongUsage();
wrongUsage() if @ARGV;

#--------------------------------
# Initialisation of the variables

# for limiting runing time to $timelimit
my $startime = time;

# see if we build a gnome or a kde menu.
$DESKTOP = 'Kde'   if ( $MENU_NAME =~ /kde/ );
$DESKTOP = 'Gnome' if ( $MENU_NAME =~ /gnome/ );

if ( $OPT_INSTALL_PREFIX ne '' ) {
	$APPS_DIR = $GNOME_APPS = "$OPT_INSTALL_PREFIX/share/gnome/apps";
	$KDE_APPS = "$OPT_INSTALL_PREFIX/share/applnk";
	$KDE_MINI_ICONS = "$OPT_INSTALL_PREFIX/share/icons/mini";
	$KDE_ICONS = "$OPT_INSTALL_PREFIX/share/icons";
	#$GNOME_ICONS = "$OPT_INSTALL_PREFIX/share/pixmaps";
}

if ( $MENU_TYPE eq 'gtk' ) {
	$flag ='gtk_';
	$MENU_DESTROY = 'no'  if ( ! $MENU_DESTROY =~ /^y/ );
} else {
	$flag ='fvwm_';
	$MENU_DESTROY = 'yes' if ( !($MENU_DESTROY =~ /^n/ 
		|| $MENU_DESTROY =~ /^d/) );
}

if ( $MENU_NAME eq 'gnome-user' ) {
	$APPS_DIR   = "$ENV{HOME}/.gnome/apps";
	$MENU_TITLE = 'Gnome User Menu';
}

if ( $MENU_NAME eq 'gnome-redhat' ) {
	$APPS_DIR   = "$ENV{HOME}/.gnome/apps-redhat";
	$MENU_TITLE = 'Gnome RedHat Menu';
}

if ( $DESKTOP eq 'Kde' && $KDE_PREFIX eq '' && $DESC_DIR eq '') {
	die "fvwm-menu-desktop: It seems that kde is _not_ installed on your\n"
		. "machine! If it is, please used the --install-prefix or the\n"
		. " --dir option (see the man page).\n";
}

if ( $MENU_NAME eq 'kde-sys' ) {
	$APPS_DIR   = $KDE_APPS;
	$MENU_TITLE = 'Kde System Menu';
}

if ( $MENU_NAME eq 'kde-user' ) {
	$APPS_DIR   = "$ENV{HOME}/.kde/share/applnk";
	$MENU_TITLE = 'Kde User Menu';
}

if ( $DESC_DIR ne '') {
	$APPS_DIR   = $DESC_DIR;
	$DESC_DIR   =~ s/\/*$//;
	$name       = substr($DESC_DIR,rindex($DESC_DIR,'/')+1);
	$DESKTOP    = 'Kde' if ( $DESC_DIR =~ /kde/ && $DESKTOP eq '');
	$DESKTOP    = 'Gnome' if ( $DESC_DIR =~ /gnome/ && $DESKTOP eq '');
	$MENU_NAME  = $MENU_TITLE = "$name"; 
	if ( $DESKTOP ne '' ) {
		$MENU_NAME  = "$DESKTOP-$MENU_NAME";
		$MENU_TITLE = "$DESKTOP $name";
	}
}

# Menu Title is recomputed later if $opt_menu_name is undef
# (try to use Desktop hints).
$MENU_NAME  = $OPT_MENU_NAME  if ( $OPT_MENU_NAME ne '' );
$MENU_TITLE = $OPT_MENU_TITLE if ( $OPT_MENU_TITLE ne '' );

# Prefix for submenu:
if ($SUBMENUS_PREFIX ne '')  { $SUBMENUS_PREFIX = "$SUBMENUS_PREFIX-" }
else { $SUBMENUS_PREFIX = "$MENU_NAME-" }


# ---------
# Icon init


if ( $TRAN ) { $MINI_ICONS = 1 }

if ( $MINI_ICONS_DIR ne 'mini/' || $ICONS_DIR ne '') {
	if ($MINI_ICONS_DIR ne '' ) { $MINI_ICONS_DIR =~ s/\/*$/\// };
	if ( $ICONS_DIR eq '' ) {
		$ICONS_DIR = up_directory($MINI_ICONS_DIR)
	} else {
		if ( $ICONS_DIR eq 'inpath' ) { $ICONS_DIR = '' }
		else { $ICONS_DIR =~ s/\/*$/\//  if ($MINI_ICONS_DIR ne '' ) }
	}
}

if ( $TRAN_MINI_ICONS ne 'mini/' || $TRAN_ICONS ne '' ) {
	if ($TRAN_MINI_ICONS ne '' ) { $TRAN_MINI_ICONS =~ s/\/*$/\// };
	if ( $TRAN_ICONS eq '' ) {
		$TRAN_ICONS = up_directory($TRAN_MINI_ICONS) 
	} else { 
		if ( $TRAN_ICONS eq 'inpath' ) { $TRAN_ICONS = '' }
		else { $TRAN_ICONS =~ s/\/*$/\// if ($TRAN_ICONS ne '' ) }
	}
}

$PNG_ICONS =~  s/\/*$/\// if ($PNG_ICONS ne '');

# init default mini-icons, law, place, sidepic, color

foreach $i (qw(folder title toptitle app)) {
	$DI{"gtk_$i"} =  $DI{"fvwm_$i"};
}

if ( $flag eq 'gtk_') {
	foreach $i (qw(gtk_app gtk_folder gtk_title gtk_toptitle)) {
		$dmicon{$i} = "$PNG_ICONS$dmicon{$i}";
		@list       = split(':',$DI{$i});
		$l = @list;
		while ( $l <= 2 ) { push(@list,''); ++$l }
		$law{$i} = $list[1] if  ($list[1] eq 'no'  || $list[1] eq 'ow' 
		    ||  $list[1] eq 're' || $list[1] eq 'dh' );
		$dmicon{$i} = "$PNG_ICONS$list[0]" if ( $list[0] ne '' );
		$dmicon{$i} = '' if ( $law{$i} eq 'no' || !$MINI_ICONS );
	}
} else {
	foreach $i (qw(fvwm_app fvwm_folder fvwm_title fvwm_toptitle)) {
		# With the mini-icons-tran options we "use" gtk default
		if ( $TRAN ) {
			$j = substr($i,index($i,'_'));
			$j = "gtk$j";
			$law{$i} = $law{$j};
			$tmp_icon  = $dmicon{$j};
			$tmp_icon  =~ s/\.png$/\.xpm/;
			$dmicon{$i} = "$TRAN_MINI_ICONS$tmp_icon";
		} else {
			$dmicon{$i} = "$MINI_ICONS_DIR$dmicon{$i}";
		}
		@list = split(':',$DI{$i});
		$l = @list;
		while ( $l <= 5 ) { push(@list,''); ++$l }
		$law{$i}     = $list[1] if ($list[1] eq 'no'  || $list[1] eq 'ow' 
			|| $list[1] eq 're' || $list[1] eq 'dh' );
		$dmicon{$i}  = "$MINI_ICONS_DIR$list[0]" if ( $list[0] ne '' );
		$place{$i}   = '*' if ($list[2] eq 'up');
		$dmicon{$i}  = "$place{$i}$dmicon{$i}$place{$i}";
		$dmicon{$i}  = '' if ($law{$i} eq 'no' || $MINI_ICONS == 0);
		if ( $list[3] ne '' ) { $spic{$i}   = "\@$list[3]\@" }
		else { $spic{$i}   = '' } 
		if ( $list[4] ne '' && $list[3] ne '' ) { $scolor{$i} = "\^$list[4]\^" }
		else {$scolor{$i} = ''};
	}
}

# style init
if ( $TRAN_STYLE ) { $STYLE = 1 }

if ( $STYLE ) { 
	
	@list= split(':',$ICON_STYLE);
	$l = @list;
	while ( $l <= 4 ) { push(@list,''); ++$l }
	
	if ( $TRAN_STYLE || $TRAN ) {
		if ( $list[0] ne '' ) { $dstyle{mini_icon} = $TRAN_MINI_ICONS . $list[0] }
		else { $dstyle{mini_icon} = $TRAN_MINI_ICONS . $dstyle{gnome_mini_icon} }
		if ( $list[1] ne '' ) { $dstyle{icon} = $TRAN_ICONS . $list[1] } 
		else { $dstyle{icon} = $TRAN_ICONS . $dstyle{gnome_icon} }
	} else {
		if ( $list[0] ne '' ) { $dstyle{mini_icon} = $MINI_ICONS_DIR . $list[0] } 
		else { $dstyle{mini_icon} = $MINI_ICONS_DIR . $dstyle{mini_icon} }
		if ( $list[1] ne '' ) { $dstyle{icon} = $ICONS_DIR . $list[1] } 
		else { $dstyle{icon} = $ICONS_DIR . $dstyle{icon} }
	}
	
	$style_law = $list[2] if ( $list[2] eq 'dh' ||   $list[2] eq 'ow' 
		|| $list[2] eq 're' );
	$addstyle = $list[3] if ( $list[3] ne '' );

}

#----------------
# "Main" variable: contains the directories to look at.
# + is the "level" separator, the menu is builded level by level
# with a double loop 
@Rec_Dir_List = ("$APPS_DIR", "+");

# init level
# what is the function count("/", $dir) ?
$level = 0;
$cdir = $APPS_DIR;
while ( $cdir =~ /\// ) {
	$cdir =~ s/\///;
	++$level;
}
$top_level = $level;
$nlevel = $level +1;		# next level


#---------------------------------
# Main loop (double loop)
while( $Rec_Dir_List[0] ne '+') {
	
	# construct a level (may add some .fvwm2rc comment here)
	while( $Rec_Dir_List[0] ne '+') {
	
		$dir = $Rec_Dir_List[0]; # current working directory
		@Main_List=();	# will contain the list of the file and dir
		#               # of $dir (in good order)
	
		#--------
		# Construct the Main_List:
		# 1. look at an "order" hint and begin the list
		# 2. complet the list
	
		# 1. Look to the desktop order hint
		# For gnome there is an .order file. For kde the order is in the
		# .directory file.  
	
		# for gnome
		if ( -f "$dir/.order" ) {
			open(ORDER, "$dir/.order") || print STDERR
			"fvwm-menu-desktop: Can't open $dir/.directory (not a fatal error"
			. "but this is curious, is your administrator paranoid?): $!\n";

			while( defined ($name = <ORDER>)) {
				chomp($name);
				push(@Main_List, "$dir/$name");
			}
		
			close(ORDER);
		} 
	
		# for kde
		if ( -f "$dir/.directory" ) {
			open(ORDER, "$dir/.directory") || print STDERR
			"fvwm-menu-desktop: Can't open $dir/.directory (not a fatal error but"
			. "this is curious, is your administrator paranoid ?): $!\n";
		
			while(<ORDER>) {
				if ( /^SortOrder=(.*)$/ ) {
					$order = $1;
					@list = split(/\s*,\s*/, $order);
					foreach $name (@list) { push(@Main_List, "$dir/$name") }
				}
			}
		
			close(ORDER);
		}
	
		# 2. Add to @Main_List the items not in the order.
		# AND WE UPDATE @Rec_Dir_List HERE
		@list = @Main_List;
		foreach $name (<$dir/*>) {
			$add=1;
			if ( -d $name ) { push(@Rec_Dir_List, "$name") }
			foreach $j  (@list) {
				$add=0 if ($name eq $j);
			}
			push(@Main_List, "$name") if ( $add );
		}
	
		# ---------
		# Build the menu of $dir
		build_a_level();
	
		shift(@Rec_Dir_List);
	}
	
	# next level  
	$level = $nlevel;
	++$nlevel;
	shift @Rec_Dir_List;	# push out the "+"
	push( @Rec_Dir_List, '+' );	# add a level separator
	# @Rec_Dir_List = (+) => END
}

# output the style
print "$STYLEOUTPUT" if ( $STYLE );

# end of main
#----------------------------------------------------------------------------
#----------------------------------------------------------------------------
# Subroutines:
#     up_directory
#     build_a_level (build a (sub)Menu)
#     get_info (Read Desktop hints, compute icons)
#     update_style
#     check_app
#
#----------------------------------------------------------------------------
#----------------------------------------------------------------------------
# Compute cd ..
sub up_directory {
	my($dir) = @_;
	
	if ( $dir eq '' ) { return '../' }
	chop($dir);
	if ( ! ($dir =~ /\//) ) { return '' }
	$dir = substr($dir,0,rindex($dir,'/')+1);
	return $dir;
}

#----------------------------------------------------------------------------
# Build a (sub)menu
sub build_a_level {
	my ($label, $exec, $mini_icon) = ('', '', '');
	my ($style_mini_icon,$style_icon) = ('', '');
	my $titletype; 
	my $tmp_name; 
	my $name; 
	my $item;
	
	
	# Head of the menu
	
	if ( $level == $top_level ) {
	
		$mini_icon = $dmicon{$flag .'toptitle'};
		$name = $MENU_NAME;
		($label, $mini_icon) = get_info("$APPS_DIR/.directory", 'toptitle')
			if ( -f "$dir/.directory" );
		if ( $label eq '' || $OPT_MENU_TITLE ne '') { $label = $MENU_TITLE } 
		else { $label = "$DESKTOP $label" }
		$titletype = 'toptitle';

	} else {
	
		$tmp_name = substr($dir,rindex ($dir,'/')+1);
		$name = "$SUBMENUS_PREFIX$tmp_name-$level";
		if ( -f "$dir/.directory" ) {
			($label, $mini_icon) = get_info("$dir/.directory", 'title');
		} else {
			print STDERR "fvwm-menu-desktop: Bad menu description\n";
			$mini_icon = $dmicon{$flag . 'title'};
		}
		$label = $tmp_name if ( $label eq '');
		$titletype = 'title';
	}
	
	# Now we can print the Head of the (sub)menu
	if ( $flag eq 'gtk_' ) {
	
		print "*${fvwmGtkName}Destroy \"$name\"\n" if ( $level == $top_level
			&& $MENU_DESTROY =~ /^y/ );
		print "*${fvwmGtkName}Menu \"$name\"\n" .
			"*${fvwmGtkName}Title \"$label\" $mini_icon\n" .
			"*${fvwmGtkName}Separator\n";
	
	} else {
	
		if ( $level != $top_level || $MENU_DESTROY =~ /^y/ ) { 
			print "DestroyMenu \"$name\"\n";
		} elsif ( $MENU_DESTROY =~ /^d/ ) {
			print "DestroyMenu recreate \"$name\"\n";
		}
		print "AddToMenu \"$name$spic{\"$flag$titletype\"}" .
			"$scolor{\"$flag$titletype\"}\" \"$label$mini_icon\" Title\n";
	
	}
	
	# Items of the menu
	for $item (@Main_List) {
	
		#PB (good place ??)
		if ( ((time - $startime) >= $timelimit) && $IKWID != 1 ) {
			die "fvwm-menu-desktop decides to die because it thinks that it\n" 
			. "run to much time (see the man page)"
		}
	
		$tmp_name = substr($item,rindex ($item,'/')+1);
	
		# If it is a dir --> a popup (folder)
		if ( -d $item ) {
			$name = "$SUBMENUS_PREFIX$tmp_name-$nlevel";
			($label, $mini_icon) = get_info("$item/.directory", 'folder') 
				if (-f "$item/.directory");
			$label= $tmp_name if ( $label eq "");
			if ( $flag eq 'gtk_' ) {
				print "*${fvwmGtkName}Destroy $name\n";
				print "*${fvwmGtkName}SubMenu \"$label\" \"$name\" $mini_icon\n";
			} else { 
				print "+ \"$label$mini_icon\" Popup \"$name\"\n";
			}
		}
	
		# a file --> application
		if (-f $item ) {
			($name, $mini_icon, $exec) = get_info($item, 'app');
			if ( $exec ne '' ) {
				if ( $flag  eq 'gtk_' ) {
					print "*${fvwmGtkName}Item \"$name\" \"Exec exec $exec\" " .
					"$mini_icon\n";
				} else {
					print "+ \"$name$mini_icon\" Exec exec $exec\n";
				}
			}
		}
	
		# for kde
		if ( $item eq "$dir/SEPARATOR") {
			if  ( $flag  eq 'gtk_' ) {
				print "*${fvwmGtkName}Separator\n";
			} else {
				print "+ \"\" Nop\n";
			}
		}
	
	}
}


# ---------------------------------------------------------------------------
# Read Desktop hints, compute the (mini-)icon and build the STYLE (via a sub)

sub get_info {
	my($file,$which) = @_;
	my($label, $mini_icon, $exec) = ('', '', '', '');
	my($icon, $tran_icon, $tran_mini_icon) = ('', '', '', '');
	my $term = 0;
	my($deflabel, $onelabel) = ('', '');
	my $exec_exec = '';
	my($style_icon, $style_mini_icon) = ('', '');
	
	open(DESC,$file) || die "fvwm-menu-desktop: can't open $file: $!";
	while(<DESC>) {
		
		if ( /^Name\[$LANG\]=(.*)$/ ) { $label = $1 }
		
		if (/^Name=(.*)$/) { $deflabel = $1 }
		
		# we need one label, may be usefull for freind user menu with 
		# other lang
		if (/^Name.*=(.*)$/) { $onelabel = $1 }
		
		if ( /^Exec=((\S*).*$)/ ) {
			$exec = $1;
			$exec_exec = $2;
		}
		
		$term = 1 if (/^Terminal=1/);
		
		if ( /^Icon=(.*)$/ ) { $icon = substr($1,rindex($1,'/')+1) }
			 
		# kde gives sometimes a mini-icon hint
		if ( /^MiniIcon=(.*)$/ ) { $mini_icon = substr($1,rindex($1,'/')+1) }
			 
	}

	close(DESC);
		
	#----------------------
	# See which info we get
	
	$label = $deflabel if ( $label eq '');
	$label = $onelabel if ( $label eq '');
	
	if ( $which eq 'app' ) {
		# kde introduce some %foo things after the executable for options
		# "%c" is for the name (caption option)
		# other things seems unusefull for us !
		# (%i is for icon, %m is for mini-icon, %u is for ??user?? and
		# %f is for file I presume, but what file ???)
		# we use caption 
		$exec =~ s/\"\%c\"/\"$label\"/;
		$exec =~ s/\%.//g;
		
		# check the existance of the app
		return('', '', '') if $CHECK && !check_app($exec_exec);
		
		# term
		$exec = "$TERM_CMD $exec" if $term;
		
		#sometimes kde workers forget the icons and the mini-icons:
		if ( $mini_icon eq '' && $APPS_DIR eq  $KDE_APPS) {
			$mini_icon = "$exec_exec.xpm" 
				if ( -f "$KDE_MINI_ICONS$exec_exec.xpm" );
			$icon = "$exec_exec.xpm" 
				if ( -f "$KDE_ICONS$exec_exec.xpm" );
		}
		
	}
	
	#----------------------------
	# if no icons or ow and no style we can return now
	return($label, $dmicon{$flag . $which}, $exec) 
		if ( ($law{"$flag$which"} eq 'ow'
			|| $law{"$flag$which"} eq 'no'
			|| !$MINI_ICONS) && !$STYLE );
	
	#--------------
	# now the icons
	
	$mini_icon = $icon if ( $mini_icon eq '');
	$icon = $mini_icon if  ( $icon eq '');
	
	
	# Translation
	# for mini-icons-tran && style(-tran) (we translate only the mini-icon 
	# since gnome do not specify minicon ...).
	if ( ($TRAN && $flag eq 'fvwm_') || ($TRAN_STYLE) ) {
		$tmp_icon = $mini_icon;
		if ( $tmp_icon =~ /\.png$/ ) {
			$tmp_icon =~ s/\.png$/\.xpm/;
			$tran_mini_icon = $tmp_icon if ( (-f "$TRAN_MINI_ICONS$tmp_icon")
				|| !($TRAN_MINI_ICONS =~ /^\//) );
			$tran_icon = $tmp_icon if ( (-f "$TRAN_ICONS$tran_mini_icon")
				|| !($TRAN_ICONS =~ /^\//) );
		}
	}
	
	
	# no .png icons with fvwm menu
	$mini_icon = '' if ( $flag eq 'fvwm_' && $mini_icon =~ /\.png$/ );
	
	# Ok the icons are computed except the path.
	
	# Style
	if ( $STYLE && $which eq 'app' ) {
		if ( $tran_mini_icon ne '' )  { 
			$style_mini_icon = $tran_mini_icon; 
		} else { 
			$style_mini_icon = $mini_icon;
			$style_mini_icon = '' if ( $mini_icon =~ /\.png$/ ); 
		}
		if ( $tran_icon ne '' ) { 
			$style_icon = $tran_icon 
		}
		else {
			$style_icon = $icon;
			$style_icon = '' if ( $icon =~ /\.png$/ );  
		}
		update_style($style_mini_icon, $style_icon, $exec_exec) 
	}
	
	# Add the path
	if ( $TRAN && $tran_mini_icon ne '' ) { 
		$mini_icon = "$TRAN_MINI_ICONS$tran_mini_icon";
	} elsif ( $mini_icon ne '' ) {
		if ( $mini_icon =~ /\.png$/ ) { $mini_icon =  "$PNG_ICONS$mini_icon" }
		else { $mini_icon =  "$MINI_ICONS_DIR$mini_icon" }
	}
	
	
	#return the info with icon
	
	return($label, $dmicon{$flag . $which}, $exec) 
		if ( $law{"$flag$which"} eq 'ow'
			|| $law{"$flag$which"} eq 'no'
			|| $MINI_ICONS == 0
			|| ($mini_icon eq '' && $law{"$flag$which"} eq 're') );
	
	return($label, $mini_icon, $exec) 
		if ($flag eq 'gtk_');
	
	return($label,
		"$place{\"$flag$which\"}$mini_icon$place{\"$flag$which\"}", 
		$exec)
		if ( $mini_icon ne '' );
	
	return($label, '', $exec);
}


# ---------------------------------------------------------------------------
# Update style

sub update_style {
	my($style_mini_icon, $style_icon, $exec_exec) = @_;
	
	# Gnome exeption for $exec_exec, I probably forget some ...
	# seems that there is a rule ...
	$exec_exec = 'GnomeTerminal' if ( $exec_exec eq 'gnome-terminal' );
	$exec_exec = 'Imlib Config Editor' if ( $exec_exec eq 'imlib_config' );
	$exec_exec = 'GnomeHelpBrowser' if ( $exec_exec eq 'gnome-help-browser' );
	$exec_exec = 'GQview' if ( $exec_exec eq 'gqview' );
	
	# kde exeptions. Some families of apps have the same name, class, ressource
	# for windows manager, but kwm; (I try the caption and icon option with
	# kcminfo but do not succed ...)
	# Anyway some of the concerned applications are kwm specifics.
	
	if ( $exec_exec eq 'kfmclient' ) {
		$style_icon = $style_mini_icon = 'kfm.xpm'; #kfm_home.xpm better ???
		$exec_exec = 'kfm';
	}
	
	$style_icon = $style_mini_icon = 'information_settings.xpm' 
		if ( $exec_exec =~ /^kcminfo/ );
	$style_icon = $style_mini_icon = 'kcmkwm.xpm' 
		if ( $exec_exec =~ /^kcmdisplay/ );
	$style_icon = $style_mini_icon = 'input_device_settings.xpm' 
		if ( $exec_exec =~ /^kcminput/ );
	$style_icon = $style_mini_icon =  'kwm.xpm'
		if ( $exec_exec =~ /^kcmkwm/ );
	
	# Now we add the good path
	if ( $TRAN_STYLE || $TRAN ) {
		$style_mini_icon = "$TRAN_MINI_ICONS$style_mini_icon"
			if ( $style_mini_icon ne '');
		$style_icon = "$TRAN_ICONS$style_icon" if ( $style_icon ne '');
	} else {
		$style_mini_icon =  "$MINI_ICONS_DIR$style_mini_icon" 
			if ( $style_mini_icon ne '' );
		$style_icon =  "$ICONS_DIR$style_icon"  if ( $style_icon ne '' );
	}
	
	if (($style_mini_icon eq '' && $style_law eq 're') || ($style_law eq 'ow')) {
		$style_mini_icon = $dstyle{mini_icon};
	}
	
	if (($style_icon eq '' && $style_law eq 're') || ($style_law eq 'ow')) {
		$style_icon = $dstyle{icon};
	}
	
	# Update $STYLEOUTPUT
	if ( $style_mini_icon ne '' || $style_icon ne '' || $addstyle ne '' ) {
		$STYLEOUTPUT .= "Style \"$exec_exec\" MiniIcon " . "$style_mini_icon\n"
			if  ( $style_mini_icon ne '' );
		$STYLEOUTPUT .= "Style \"$exec_exec\" Icon $style_icon\n"
			if  ( $style_icon ne '' );
		$STYLEOUTPUT .= "Style \"$exec_exec\" $addstyle\n"
			if  ( $addstyle ne '' );
	}
}


#--------------------------------------------------------------------------
# Check if an application is in the path

sub check_app {
	my($app) = @_;
	foreach $dir (@PATH_DIRS) {
		if ( -x "$dir/$app" ) { return 1 }
	}
	return 0;
}


#----------------------------------------------------------------------------
# Standard functions

sub showHelp {
	print <<END_HELP;
A perl script which parses gnome/kde menus definitions to build
the corresponding fvwm/FvwmGtk menu.  The script can also build
Icon and MiniIcon style for the desktop applications.

Usage: $0 [OPTIONS]
Options:
	--help                    show this help and exit
	--version                 show version and exit
	--install-prefix DIR      install prefix of the desktop
	--desktop NAME            desktop to build the menu for it:
		gnome-sys (default), gnome-user, gnome-redhat,
		kde-sys, kde-user
	--type NAME               fvwm (default) or gtk for a FvwmGtk menu
	--fvwm-gtk-name NAME      FvwmGtk module name, default is FvwmGtk
	--title NAME              menu title, default depends on --desktop
	--name NAME               menu name, default depends on --desktop
	--enable-mini-icons       enable mini-icons in menu
	--enable-tran-mini-icons  enable mini-icons in menu and
		translation of foo.png icon names to foo.xpm
	--mini-icons-path DIR     path of menus icons (relative to your
		ImagePath), default is 'mini/'
	--png-icons-path DIR      path of .png icons, default is your ImagePath
	--tran-mini-icons-path DIR      path of menus icons for translation
	--icon-toptitle micon:law:place:sidepic:color  mini-icon for the top
		 title and sidepic for the top menu
	--icon-title micon:law:place:sidepic:color     as above for submenus
	--icon-folder micon:law:place   mini-icons for folder item
	--icon-app micon:law:place      mini-icon for applications item
	--enable-style            build icons and mini-icons style
	--enable-tran-style       as above with translation (for FvwmGtk menus)
	--icon-style micon:icon:law     icons for style
	--icons-path DIR          define the directory of the icons,
		the default is very good
	--tran-icons-path DIR     similar to the above option.
	--submenu-name-prefix NAME      in general not useful
	--dir DIR                 use path as desktop menu description
	--destroy-type FLAG       how to destroy menu, valid values:
		'yes', 'no', 'dynamic', the default depends on --type
	--xterm CMD               complete terminal command to run applications
		in it, default is 'xterm -e'
	--lang NAME               language, default is \$LANG
	--[no]check-app           [do not] check that apps are in your path
	--i-know-what-i-do        so, ...
Short options are ok if not ambiguous: -h, -x, -icon-a.
END_HELP
	exit 0;
}

sub showVersion {
	print "$version\n";
	exit 0;
}

sub wrongUsage {
	print STDERR "Try '$0 --help' for more information.\n";
	exit -1;
}
