3 # ---------------------------------------------------------------------------
5 # See the man page fvwm-menu-desktop.1 for instructions.
7 # Created on 22/07/1999 by Olivier Chapuis
9 # Updated on 15/08/1999 by Mikhael Goikhman
11 # ---------------------------------------------------------------------------
14 # The script is distributed by the same terms as fvwm itself.
15 # See GNU General Public License for details.
17 #----------------------------------------------------------------------------
23 # For command line options
26 my $version = "@VERSION@";
29 # Defaults (most of them can be modified with the options)
33 my $GNOME_PREFIX = '/usr'; # gnome install-dir
34 # Default is "gnome" since fvwm is gnome compliant and not kde compliant.
35 my $APPS_DIR = -d "$GNOME_PREFIX/share/gnome/apps" ?
36 "$GNOME_PREFIX/share/gnome/apps" :
37 "$GNOME_PREFIX/share/gnome/applications";
38 my $GNOME_APPS = $APPS_DIR;
39 my $KDE_PREFIX = $ENV{KDEDIR} || '/usr';
40 my $KDE_APPS = "$KDE_PREFIX/share/applnk";
41 my $KDE_MINI_ICONS = "$KDE_PREFIX/share/icons/mini/";
42 my $KDE3_MINI_ICONS = "$KDE_PREFIX/share/icons/hicolor/16x16/apps/";
43 my $KDE_ICONS = "$KDE_PREFIX/share/icons/";
44 my $KDE3_ICONS = "$KDE_PREFIX/share/icons/hicolor/48x48/apps/";
45 my $OPT_INSTALL_PREFIX = '';
47 # Default for the mini-icons is mini/ (relatively to the ImagePath)
48 my $MINI_ICONS_DIR = 'mini/';
49 # Then the default for icon is ImagePath (consistent with kde, fvwm2gnome
50 # and almost consistent with wm-icons)
54 # Default for mini-icons and icons translation
55 my $TRAN_MINI_ICONS = 'mini/';
58 #Unused path at the present time
59 #$GNOME_ICONS = "$GNOME_PREFIX/share/pixmaps/";
62 my $MENU_TITLE = 'Gnome System Menu'; # default top title
63 my $MENU_NAME = 'gnome-sys'; # default top menu name
64 my $MENU_TYPE = 'fvwm'; # default menu type
65 my $DESKTOP = ''; # will contain Kde or Gnome if possible
66 my $OPT_MENU_TITLE = '';
67 my $OPT_MENU_NAME = '';
68 my $fvwmgtk_name = "FvwmGtk"; # FvwmGtk module name
72 # mini-icons default (app for application, folder for folder, title for
73 # submenu title, toptitle for the top title, fvwm_ for fvwm menu, gtk_ for
74 # FvwmGtk menu) the variable $flag will be fvwm_ or gtk_. Use kde
75 # default icons for fvwm menus and gnome icons for gtk menus
78 $DI{fvwm_app} = 'mini-x.xpm:dh:%::'; # micon:law:placement:unused
79 $DI{fvwm_folder} = 'folder.xpm:dh:%::'; # idem
80 $DI{fvwm_title} = 'folder.xpm:dh:%::'; # micon:law:place:spic:color
81 $DI{fvwm_toptitle} = 'mini-k.xpm:no:%::'; # idem
82 $DI{gtk_app} = 'gnome-default.png:dh:::'; # idem
83 $DI{gtk_folder} = 'gnome-folder.png:dh:::'; # micon:law:unused
84 $DI{gtk_title} = 'gnome-folder.png:dh:::'; # idem
85 $DI{gtk_toptitle} = 'gnome-logo-icon-transparent.png:no:::'; # idem
96 foreach $i (keys(%DI)) {
97 @list = split(':',$DI{$i});
98 $dmicon{$i} = $list[0]; # "default" mini-icon
99 $law{$i} = $list[1]; # default law
100 $place{$i} = $list[2]; # default position
101 $spic{$i} = $list[3]; # sidepic icon
102 $scolor{$i} = $list[4]; # color for sidepic
106 my $MINI_ICONS = 0; # mini-icon disabled (enable =1)
107 my $TRAN = 0; # mini-icon translation disabled (enable =1)
108 my $wm_icons = 0; # use wm-icons compatible menu icon names
113 $dstyle{mini_icon} = 'mini-x.xpm'; # default MiniIcons Style
114 $dstyle{gnome_mini_icon} = 'gnome-default.xpm';
115 $dstyle{icon} = 'x.xpm'; # default Icons Style
116 $dstyle{gnome_icon} = 'gnome-default.xpm';
117 my $style_law = 'dh'; # default law
118 my $addstyle = ''; # a style to add every where
119 my $STYLE = 0; # style is disable (enable =1)
120 my $TRAN_STYLE = 0; # translation for style is disabled (enable =1)
121 my $STYLEOUTPUT = ''; # The styles are in this variable
125 # default term for runnig applications in a terminal
126 my $TERM_CMD = "xterm -e";
130 my $timelimit = 15; # limit runing time for the script
131 my $LANG = $ENV{LANG} || ""; # Internationalization support :o)
132 my $UTF8 = 0; # KDE2 use UTF-8
133 my $UTF8_TR = ""; # charset type for UTF-8 translation
134 my $UNICONV = ""; # use a convert tool for UTF8 tr
135 my $UNICONV_EXEC = ""; # iconv, uniconv or internal
136 my @PATH_DIRS = split(':',$ENV{PATH}); # for checking if applications exist
137 my $CHECK = 1; # we check by default
138 my $MENU_DESTROY = '';
140 my $SUBMENUS_PREFIX = '';
144 my @menus_for_style = ();
155 my @Rec_Dir_List = ();
161 my $merge_user_menu = 0;
163 my $merge_user_dir = "";
165 my $merge_dir_type = "";
166 my $user_menu_done = 0;
168 my $check_icons = "";
169 my $check_mini_icons = "";
170 my @check_icons_path = ();
171 my @check_mini_icons_path = ();
177 "help|h|?" => \&show_help,
178 "version|v|V" => \&show_version,
179 "install-prefix:s" => $OPT_INSTALL_PREFIX,
180 "desktop:s" => \$MENU_NAME,
181 "type:s" => \$MENU_TYPE,
182 "fvwmgtk-alias=s" => \$fvwmgtk_name,
183 "title:s" => \$OPT_MENU_TITLE,
184 "name:s" => \$OPT_MENU_NAME,
185 "enable-mini-icons" => \$MINI_ICONS,
186 "enable-tran-mini-icons" => \$TRAN,
187 "mini-icons-path:s" => \$MINI_ICONS_DIR,
188 "png-icons-path:s" => \$PNG_ICONS,
189 "tran-mini-icons-path:s" => \$TRAN_MINI_ICONS,
190 "icon-toptitle:s" => \$DI{"fvwm_toptitle"},
191 "icon-title:s" => \$DI{"fvwm_title"},
192 "icon-folder:s" => \$DI{"fvwm_folder"},
193 "icon-app:s" => \$DI{"fvwm_app"},
194 "enable-style" => \$STYLE,
195 "enable-tran-style" => \$TRAN_STYLE,
196 "icon-style:s" => \$ICON_STYLE,
197 "icons-path:s" => \$ICONS_DIR,
198 "tran-icons-path:s" => \$TRAN_ICONS,
199 "submenu-name-prefix:s" => \$SUBMENUS_PREFIX,
200 "dir:s" => \$DESC_DIR,
201 "destroy-type:s" => \$MENU_DESTROY,
202 "xterm:s" => \$TERM_CMD,
205 "uniconv=s" => \$UNICONV,
206 "uniconv-exec=s" => \$UNICONV_EXEC,
207 "menu-style=s" => \$MENU_STYLE,
208 "check-app!" => \$CHECK,
209 "wm-icons" => \$wm_icons,
210 "time-limit=s" => \$timelimit,
211 "merge-user-menu" => \$merge_user_menu,
212 "check-mini-icon=s" => \$check_mini_icons,
213 "check-icons=s" => \$check_icons,
215 wrong_usage() if @ARGV;
217 die "fvwm-menu-desktop: Incorrect alias ($fvwmgtk_name) is given\n"
218 if $fvwmgtk_name !~ /^\w[\w\d\.-]*$/;
220 sub print_module_config (@) {
222 print "*${fvwmgtk_name}: $_\n";
226 #--------------------------------
227 # INITIALISATION of the variables
229 # for limiting running time to $timelimit
231 $timelimit = 300 if $timelimit <= 0 || $timelimit > 300;
233 # see if we build a gnome or a kde menu.
234 $DESKTOP = 'Kde' if ( $MENU_NAME =~ /kde/ );
235 $DESKTOP = 'Gnome' if ( $MENU_NAME =~ /gnome/ );
237 if ( $OPT_INSTALL_PREFIX ne '' ) {
238 $APPS_DIR = $GNOME_APPS = "$OPT_INSTALL_PREFIX/share/gnome/apps";
239 $KDE_APPS = "$OPT_INSTALL_PREFIX/share/applnk";
240 $KDE_MINI_ICONS = "$OPT_INSTALL_PREFIX/share/icons/mini";
241 $KDE3_MINI_ICONS = "$OPT_INSTALL_PREFIX/share/icons/hicolor/16x16/apps/";
242 $KDE_ICONS = "$OPT_INSTALL_PREFIX/share/icons";
243 $KDE3_ICONS = "$OPT_INSTALL_PREFIX/share/icons/hicolor/48x48/apps/";
244 #$GNOME_ICONS = "$OPT_INSTALL_PREFIX/share/pixmaps";
247 if ( $MENU_TYPE eq 'gtk' ) {
249 $MENU_DESTROY = 'no' if ( ! $MENU_DESTROY =~ /^y/ );
252 $MENU_DESTROY = 'yes' if ( !($MENU_DESTROY =~ /^n/
253 || $MENU_DESTROY =~ /^d/) );
256 if ( $MENU_NAME eq 'gnome-sys' && $merge_user_menu) {
257 $merge_user_dir = "$ENV{HOME}/.gnome/apps";
260 if ( $MENU_NAME eq 'gnome-user' ) {
261 $APPS_DIR = "$ENV{HOME}/.gnome/apps";
262 $MENU_TITLE = 'Gnome User Menu';
265 if ( $MENU_NAME eq 'gnome-redhat' ) {
266 $APPS_DIR = "$ENV{HOME}/.gnome/apps-redhat";
267 $MENU_TITLE = 'Gnome RedHat Menu';
269 if ( $MENU_NAME eq 'gnome-mandriva' ) {
270 $APPS_DIR = "$ENV{HOME}/.gnome/apps-mdk";
271 $MENU_TITLE = 'Gnome Mandriva Menu';
279 if ( $DESKTOP eq 'Kde' && $KDE_PREFIX eq '' && $DESC_DIR eq '') {
280 die "fvwm-menu-desktop: It seems that kde is _not_ installed on your\n"
281 . "machine! If it is, please use the --install-prefix or the\n"
282 . "--dir option (see the man page).\n";
285 if ( $MENU_NAME eq 'kde-sys' ) {
286 $APPS_DIR = $KDE_APPS;
287 $MENU_TITLE = 'Kde System Menu';
288 if ($merge_user_menu) {
289 $merge_user_dir = "$ENV{HOME}/.kde/share/applnk";
293 if ( $MENU_NAME eq 'kde-user' ) {
294 $APPS_DIR = "$ENV{HOME}/.kde/share/applnk";
295 $MENU_TITLE = 'Kde User Menu';
298 if ( $DESC_DIR ne '') {
299 $APPS_DIR = $DESC_DIR;
300 $DESC_DIR =~ s/\/*$//;
301 $name = substr($DESC_DIR,rindex($DESC_DIR,'/')+1);
302 $DESKTOP = 'Kde' if ( $DESC_DIR =~ /kde/ && $DESKTOP eq '');
303 $DESKTOP = 'Gnome' if ( $DESC_DIR =~ /gnome/ && $DESKTOP eq '');
304 $MENU_NAME = $MENU_TITLE = "$name";
305 if ( $DESKTOP ne '' ) {
306 $MENU_NAME = "$DESKTOP-$MENU_NAME";
307 $MENU_TITLE = "$DESKTOP $name";
311 # Menu Title is recomputed later if $opt_menu_name is undefined
312 # (try to use Desktop hints).
313 $MENU_NAME = $OPT_MENU_NAME if ( $OPT_MENU_NAME ne '' );
314 $MENU_TITLE = $OPT_MENU_TITLE if ( $OPT_MENU_TITLE ne '' );
316 # Prefix for submenu:
317 if ($SUBMENUS_PREFIX ne '') { $SUBMENUS_PREFIX = "$SUBMENUS_PREFIX-" }
318 else { $SUBMENUS_PREFIX = "$MENU_NAME-" }
326 $MINI_ICONS_DIR = "";
327 $DI{"fvwm_toptitle"} = "menu/folder-open.xpm:ow";
328 $DI{"fvwm_title"} = "menu/folder-open.xpm:ow";
329 $DI{"fvwm_folder"} = "menu/folder.xpm:ow";
330 $DI{"fvwm_app"} = "menu/utility.xpm:ow";
333 if ( $TRAN ) { $MINI_ICONS = 1 }
335 if ( $MINI_ICONS_DIR ne 'mini/' || $ICONS_DIR ne '') {
336 if ($MINI_ICONS_DIR ne '' ) { $MINI_ICONS_DIR =~ s/\/*$/\// };
337 if ( $ICONS_DIR eq '' ) {
338 $ICONS_DIR = up_directory($MINI_ICONS_DIR)
340 if ( $ICONS_DIR eq 'inpath' ) { $ICONS_DIR = '' }
341 else { $ICONS_DIR =~ s/\/*$/\// if ($MINI_ICONS_DIR ne '' ) }
345 if ( $TRAN_MINI_ICONS ne 'mini/' || $TRAN_ICONS ne '' ) {
346 if ($TRAN_MINI_ICONS ne '' ) { $TRAN_MINI_ICONS =~ s/\/*$/\// };
347 if ( $TRAN_ICONS eq '' ) {
348 $TRAN_ICONS = up_directory($TRAN_MINI_ICONS)
350 if ( $TRAN_ICONS eq 'inpath' ) { $TRAN_ICONS = '' }
351 else { $TRAN_ICONS =~ s/\/*$/\// if ($TRAN_ICONS ne '' ) }
355 $PNG_ICONS =~ s/\/*$/\// if ($PNG_ICONS ne '');
357 # init default mini-icons, law, place, sidepic, color
359 foreach $i (qw(folder title toptitle app)) {
360 $DI{"gtk_$i"} = $DI{"fvwm_$i"};
363 if ( $flag eq 'gtk_') {
364 foreach $i (qw(gtk_app gtk_folder gtk_title gtk_toptitle)) {
365 $dmicon{$i} = "$PNG_ICONS$dmicon{$i}";
366 @list = split(':',$DI{$i});
368 while ( $l <= 2 ) { push(@list,''); ++$l }
369 $law{$i} = $list[1] if ($list[1] eq 'no' || $list[1] eq 'ow'
370 || $list[1] eq 're' || $list[1] eq 'dh' );
371 $dmicon{$i} = "$PNG_ICONS$list[0]" if ( $list[0] ne '' );
372 $dmicon{$i} = '' if ( $law{$i} eq 'no' || !$MINI_ICONS );
375 foreach $i (qw(fvwm_app fvwm_folder fvwm_title fvwm_toptitle)) {
376 # With the mini-icons-tran options we "use" gtk default
378 $j = substr($i,index($i,'_'));
381 $tmp_icon = $dmicon{$j};
382 $tmp_icon =~ s/\.png$/\.xpm/;
383 $dmicon{$i} = "$TRAN_MINI_ICONS$tmp_icon";
385 $dmicon{$i} = "$MINI_ICONS_DIR$dmicon{$i}";
387 @list = split(':',$DI{$i});
389 while ( $l <= 5 ) { push(@list,''); ++$l }
390 $law{$i} = $list[1] if ($list[1] eq 'no' || $list[1] eq 'ow'
391 || $list[1] eq 're' || $list[1] eq 'dh' );
392 $dmicon{$i} = "$MINI_ICONS_DIR$list[0]" if ( $list[0] ne '' );
393 $place{$i} = '*' if ($list[2] eq 'up');
394 $dmicon{$i} = "$place{$i}$dmicon{$i}$place{$i}";
395 $dmicon{$i} = '' if ($law{$i} eq 'no' || $MINI_ICONS == 0);
396 if ( $list[3] ne '' ) { $spic{$i} = "\@$list[3]\@" }
397 else { $spic{$i} = '' }
398 if ( $list[4] ne '' && $list[3] ne '' ) { $scolor{$i} = "\^$list[4]\^" }
399 else {$scolor{$i} = ''};
404 if ( $TRAN_STYLE ) { $STYLE = 1 }
408 @list= split(':',$ICON_STYLE);
410 while ( $l <= 4 ) { push(@list,''); ++$l }
412 if ( $TRAN_STYLE || $TRAN ) {
413 if ( $list[0] ne '' ) { $dstyle{mini_icon} = $TRAN_MINI_ICONS . $list[0] }
414 else { $dstyle{mini_icon} = $TRAN_MINI_ICONS . $dstyle{gnome_mini_icon} }
415 if ( $list[1] ne '' ) { $dstyle{icon} = $TRAN_ICONS . $list[1] }
416 else { $dstyle{icon} = $TRAN_ICONS . $dstyle{gnome_icon} }
418 if ( $list[0] ne '' ) { $dstyle{mini_icon} = $MINI_ICONS_DIR . $list[0] }
419 else { $dstyle{mini_icon} = $MINI_ICONS_DIR . $dstyle{mini_icon} }
420 if ( $list[1] ne '' ) { $dstyle{icon} = $ICONS_DIR . $list[1] }
421 else { $dstyle{icon} = $ICONS_DIR . $dstyle{icon} }
424 $style_law = $list[2] if ( $list[2] eq 'dh' || $list[2] eq 'ow'
425 || $list[2] eq 're' );
426 $addstyle = $list[3] if ( $list[3] ne '' );
430 if ($check_mini_icons ne "") {
431 @check_mini_icons_path = split(":", $check_mini_icons);
433 if ($check_icons ne "") {
434 @check_icons_path = split(":", $check_icons);
438 # LANG init for UTF-8
440 # check if we have perl >= 5.6
444 my $l = substr($LANG,0,2);
445 # latin-1: not sure that all these lang are "latin1"!
446 $UTF8_TR = '$tmpLabel =~ tr/\0-\x{ff}//UC'
447 if " ca de es it fr gl hu is lt nl no pt sv " =~ / $l /;
451 if ($UNICONV ne "") {
452 # check whether internal method is available
453 if ($UNICONV_EXEC eq "" || $UNICONV_EXEC eq "internal") {
454 eval "use Encode 'from_to';";
455 if ($UNICONV_EXEC eq "internal" && $@) {
456 die "You don't have a good perl version to use" .
457 " 'internal' unicode conversion:\n$@";
459 $UNICONV_EXEC = $@? "iconv": "internal";
461 # setup unicode conversion
462 if ($UNICONV_EXEC eq "iconv") {
463 die "iconv not found in your path\n"
464 unless check_app("iconv");
466 $tmpLabel =~ s/'/'\\\\''/g;
467 open(U, "echo '$tmpLabel' | iconv -f UTF8 -t $UNICONV |");
468 while (<U>) { chomp; $tmpLabel = $_ }
471 } elsif ($UNICONV_EXEC eq "uniconv") {
472 die "uniconv not found in your path\n"
473 unless check_app("uniconv");
475 $tmpLabel =~ s/'/'\\\\''/g;
476 open(U, "echo '$tmpLabel' | uniconv -I UTF8 -O $UNICONV |");
477 while (<U>) { chomp; $tmpLabel = $_ }
480 } elsif ($UNICONV_EXEC eq "internal") {
481 $UTF8_TR = 'from_to($tmpLabel, "utf-8", "$UNICONV")';
483 die "--uniconv argument must be iconv, uniconv or internal\n";
489 # "Main" variable: contains the directories to look at.
490 # + is the "level" separator, the menu is built level by level
492 if ($merge_user_menu && -d $merge_user_dir) {
493 @Rec_Dir_List = ("$merge_user_dir","+");
495 @Rec_Dir_List = ("$APPS_DIR", "+");
497 $merge_user_menu = 0;
501 # what is the function count("/", $dir) ?
504 while ( $cdir =~ /\// ) {
509 $nlevel = $level +1; # next level
510 my $is_top_level = 1;
512 #---------------------------------
513 # Main loop (double loop)
514 while( $Rec_Dir_List[0] ne '+') {
516 # construct a level (may add some .fvwm2rc comment here)
517 while( $Rec_Dir_List[0] ne '+') {
519 $dir = $Rec_Dir_List[0]; # current working directory
520 @Main_List=(); # will contain the list of the file and dir
521 # # of $dir (in good order)
523 my @orderedList = ();
532 if ($merge_user_menu) {
535 $merge_dir =~ s#^$APPS_DIR#$merge_user_dir#;
536 $sys_dir =~ s#^$merge_user_dir#$APPS_DIR#;
537 if ("$sys_dir" eq "$dir") { $merge_dir_type = "s"; }
538 else { $merge_dir_type = "u"; }
542 # Construct the Main_List:
543 # 1. look at an "order" hint and begin the list
544 # 2. complete the list
546 # 1. Look to the desktop order hint
547 # For gnome there is an .order file. For kde the order is in the
551 if ( -f "$dir/.order" ) {
552 open(ORDER, "$dir/.order") || print STDERR
553 "fvwm-menu-desktop: Can't open $dir/.order: $!\n";
554 while( defined ($name = <ORDER>)) {
556 push(@orderedList, "$dir/$name");
562 # see if the user has over read the systeme .directory:
563 if ("$merge_dir_type" eq "s" && -f "$merge_dir/.directory") {
564 open(ORDER, "$merge_dir/.directory") || print STDERR
565 "fvwm-menu-desktop: Can't open $merge_dir/.directory: $!\n";
567 $hidden = 1 if /^hidden=true/i;
568 if ( /^SortOrder=(.*)$/ ) {
571 @list = split(/\s*,\s*/, "$order");
572 foreach $name (@list) {
573 next if -f "$merge_dir/$name" && is_hidden("$merge_dir/$name");
574 push(@orderedList, "$dir/$name");
579 } elsif ( -f "$dir/.directory" ) {
580 open(ORDER, "$dir/.directory") || print STDERR
581 "fvwm-menu-desktop: Can't open $dir/.directory: $!\n";
583 $hidden = 1 if /^hidden=true/i;
584 if ( /^SortOrder=(.*)$/ ) {
587 @list = split(/\s*[,;]\s*/, "$order");
588 foreach $name (@list) {
589 next if $merge_user_menu && -f "$merge_dir/$name" &&
590 is_hidden("$merge_dir/$name");
591 push(@orderedList, "$dir/$name");
597 @orderedList = () if $hidden;
599 # 2. Add to @Main_List the items not in the order.
600 # AND WE UPDATE @Rec_Dir_List HERE
602 # a system submenu has a submenu in the user menu:
603 if ($merge_dir_type eq "s" && ! -d $dir && -d $merge_dir) {
604 foreach $name (read_dir($merge_dir)) {
605 next if $name =~ /^\./;
606 $add = (-f "$dir/$name") || is_dir_not_empty("$dir/$name");
607 if (-d "$merge_dir/$name") {
608 next if -f "$merge_dir/$name/.directory" &&
609 is_hidden("$merge_dir/$name/.directory");
610 push(@uDir, "$dir/$name") if $add;
612 foreach $j (@orderedList) { $add=0 if "$dir/$name" eq "$j"; }
613 push(@uList, "$dir/$name") if $add ;
618 foreach $name (read_dir($dir)) {
619 next if $name =~ /^\./;
620 $add = (-f "$dir/$name") || is_dir_not_empty("$dir/$name");
621 if ( -d "$dir/$name" ) {
622 if ($merge_dir_type eq "s" && -f "$merge_dir/$name/.directory") {
623 next if is_hidden("$merge_dir/$name/.directory");
625 elsif ($merge_dir_type eq "u" && -d "$sys_dir/$name") {
628 elsif ( -f "$dir/$name/.directory") {
629 next if is_hidden("$dir/$name/.directory");
631 push(@sDir, "$dir/$name") if $add;
632 } elsif ($merge_dir_type eq "s" && -f "$merge_dir/$name") {
633 next if is_hidden("$merge_dir/$name");
635 foreach $j (@orderedList) {
636 $add=0 if ("$dir/$name" eq "$j");
638 push(@sList, "$dir/$name") if $add;
642 # added user entries in a "system" submenu
643 if ($merge_dir_type eq "s" && -d "$merge_dir") {
644 foreach $name (read_dir("$merge_dir")) {
645 next if $name =~ /^\./;
646 next if -d "$dir/$name" || -f "$dir/$name";
647 next if "$dir" eq "$APPS_DIR";
648 if (-d "$merge_dir/$name") {
649 push(@uDir, "$dir/$name") if -d "$merge_dir/$name";
650 } elsif (-f "$merge_dir/$name") {
651 next if is_hidden("$merge_dir/$name");
654 foreach $j (@orderedList) {
655 $add=0 if ("$dir/$name" eq "$j");
657 push(@uList, "$dir/$name") if $add;
662 # Build the menu of $dir
664 push @Rec_Dir_List, @uDir, @sDir;
665 push @Main_List, @orderedList, @uList, @sList;
669 shift(@Rec_Dir_List);
676 shift @Rec_Dir_List; # push out the "+"
677 push( @Rec_Dir_List, '+' ); # add a level separator
678 if ($merge_user_menu && $Rec_Dir_List[0] eq '+' && !$user_menu_done) {
681 @Rec_Dir_List = ("$APPS_DIR", "+");
683 # @Rec_Dir_List = (+) => END
687 print "$STYLEOUTPUT" if ( $STYLE );
689 # output the menu style
690 if ($MENU_STYLE ne "") {
691 foreach (@menus_for_style) {
692 print qq(ChangeMenuStyle "$MENU_STYLE" "$_"\n);
697 #----------------------------------------------------------------------------
698 #----------------------------------------------------------------------------
703 # build_a_level (build a (sub)Menu)
704 # get_info (Read Desktop hints, compute icons)
708 #----------------------------------------------------------------------------
709 #----------------------------------------------------------------------------
714 opendir(DIR, $dir) || return ();
715 # put the dirs first ...
719 foreach $name (readdir(DIR)) {
720 next if $name =~ /^\./;
721 if (-d "$dir/$name") {
724 elsif (-f "$dir/$name") {
732 sub is_dir_not_empty {
735 return 0 if (! -d $dir);
736 opendir(DIR, $dir) || return 0;
737 foreach $name (readdir(DIR)) {
738 next if $name =~ /^\./;
749 return 0 if ! -f $file;
750 open(ISHIDDEN, "$file") || print STDERR
751 "fvwm-menu-desktop: Can't open $merge_dir/$file";
752 while(<ISHIDDEN>) { $return = 1 if /^hidden=true/i; }
761 if ( $dir eq '' ) { return '../' }
763 if ( ! ($dir =~ /\//) ) { return '' }
764 $dir = substr($dir,0,rindex($dir,'/')+1);
768 #----------------------------------------------------------------------------
771 my ($label, $exec, $mini_icon) = ('', '', '');
772 my ($style_mini_icon,$style_icon) = ('', '');
780 # if ( $level == $top_level ) {
782 $mini_icon = $dmicon{$flag .'toptitle'};
784 if ($merge_dir_type eq "s" && -r "$merge_dir/.directory") {
785 ($label, $mini_icon) = get_info("$merge_dir/.directory", 'toptitle')
787 if (-r "$dir/.directory") {
788 ($label, $mini_icon) = get_info("$APPS_DIR/.directory", 'toptitle')
790 if ( $label eq '' || $OPT_MENU_TITLE ne '') { $label = $MENU_TITLE }
791 else { $label = "$DESKTOP $label" }
792 $titletype = 'toptitle';
794 $tmp_name = substr($dir,rindex ($dir,'/')+1);
795 $name = "$SUBMENUS_PREFIX$tmp_name-$level";
796 $mini_icon = $dmicon{$flag . 'title'};
797 if ($merge_dir_type eq "s" && -r "$merge_dir/.directory") {
798 ($label, $mini_icon) = get_info("$merge_dir/.directory", 'title');
800 if (-r "$dir/.directory") {
801 ($label, $mini_icon) = get_info("$dir/.directory", 'title');
803 $label = $tmp_name if ( $label eq '');
804 $titletype = 'title';
807 # Now we can print the Head of the (sub)menu
808 if (!($is_top_level && $merge_user_menu && $user_menu_done)) {
809 if ( $flag eq 'gtk_' ) {
810 print_module_config qq(Destroy "$name")
811 if ( $level == $top_level && $MENU_DESTROY =~ /^y/ );
812 print_module_config qq(Menu "$name"),
813 qq(Title "$label" $mini_icon),
816 # if ( $level != $top_level || $MENU_DESTROY =~ /^y/ ) {
817 if ( (!$is_top_level || $MENU_DESTROY =~ /^y/) ) {
818 print "DestroyMenu \"$name\"\n";
819 } elsif ( $MENU_DESTROY =~ /^d/ ) {
820 print "DestroyMenu recreate \"$name\"\n";
822 print "AddToMenu \"$name$spic{\"$flag$titletype\"}" .
823 "$scolor{\"$flag$titletype\"}\" \"$label$mini_icon\" Title\n";
824 push @menus_for_style, $name;
827 if ( $flag eq 'gtk_' ) {
828 print_module_config qq(Menu "$name");
830 print "AddToMenu \"$name\" \n";
835 for $item (@Main_List) {
838 if ( time - $startime >= $timelimit ) {
839 die "fvwm-menu-desktop runs longer than time-limit; dying (see the man page)\n";
842 $tmp_name = substr($item,rindex ($item,'/')+1);
844 my $itemDD = "$item/.directory";
845 if ($merge_dir_type eq "s" && -r "$merge_dir/$tmp_name") {
846 $item = "$merge_dir/$tmp_name";
847 $itemDD = "$item/.directory" if -r "$item/.directory";
850 # If it is a dir --> a pop up (folder)
852 $name = "$SUBMENUS_PREFIX$tmp_name-$nlevel";
853 ($label, $mini_icon) = get_info("$itemDD", 'folder')
855 $label= $tmp_name if ( $label eq "");
856 if ( $flag eq 'gtk_' ) {
857 print_module_config qq(Destroy "$name"),
858 qq(SubMenu "$label" "$name" $mini_icon);
860 print "+ \"$label$mini_icon\" Popup \"$name\"\n";
864 # a file --> application
867 ($name, $mini_icon, $exec) = get_info($item, 'app');
870 if ( $flag eq 'gtk_' ) {
871 print_module_config qq(Item "$name" "Exec exec $exec" $mini_icon);
873 print "+ \"$name$mini_icon\" Exec exec $exec\n";
878 if ( $item eq "$dir/SEPARATOR") {
879 if ( $flag eq 'gtk_' ) {
880 print_module_config "Separator";
882 print qq(+ "" Nop\n);
890 # ---------------------------------------------------------------------------
891 # Read Desktop hints, compute the (mini-)icon and build the STYLE (via a sub)
894 my($file,$which) = @_;
895 my($label, $mini_icon, $exec) = ('', '', '', '');
896 my($icon, $tran_icon, $tran_mini_icon) = ('', '', '', '');
898 my($deflabel, $onelabel) = ('', '');
900 my($style_icon, $style_mini_icon) = ('', '');
902 open(DESC,$file) || die "fvwm-menu-desktop: can't open $file: $!";
904 if ( /^Name\[$LANG.*\]\s*=\s*(.*)$/ ) {
907 my $tmpLabel = $label;
908 if ($UTF8_TR ne "") { eval $UTF8_TR; $label = $tmpLabel }
909 else { $label = ""; }
913 #$label =~ s/\*/\*\*/g;
917 if (/^Name\s*=\s*(.*)$/) {
920 my $tmpLabel = $deflabel;
921 # needed for user menu!
922 if ($UTF8_TR ne "") { eval $UTF8_TR; $deflabel = $tmpLabel }
927 # Mandrake creates lines like:
928 # Exec=NO_XALF command args...
929 if ( /^Exec\s*=\s*NO_XALF\s*((\S*).*$)/ ) {
930 #print STDERR "FOUND X_ALF EXEC $1 EXEC_EXEC $2\n";
935 if ( /^Exec\s*=\s*((\S*).*$)/ ) {
941 if (/^Terminal\s*=\s*1/) {
946 if ( /^Icon=(.*)$/ ) {
947 $icon = substr($1,rindex($1,'/')+1);
951 # kde gives sometimes a mini-icon hint
952 if ( /^MiniIcon=(.*)$/ ) {
953 $mini_icon = substr($1,rindex($1,'/')+1);
959 # kde2 give just the name of the icons and use png icons
960 # try a more general fix.
962 $icon = "$icon.$tmp" if $icon !~ /\....$/ && $icon ne '';
963 $mini_icon = "$mini_icon.$tmp"
964 if $mini_icon !~ /\....$/ && $mini_icon ne '';
965 #print STDERR "$icon,$mini_icon\n";
967 #----------------------
968 # See which info we get
970 $label = $deflabel if ( $label eq '');
971 $label = $onelabel if ( $label eq '');
973 if ( $which eq 'app' ) {
974 # kde introduce some %foo things after the executable for options
975 # "%c" is for the name (caption option)
976 # other things seems useless for us !
977 # (%i is for icon, %m is for mini-icon, %u is for ??user?? and
978 # %f is for file I presume, but what file ???)
980 $exec =~ s/\"\%c\"/\"$label\"/;
983 # check the existence of the app
984 return('', '', '') if $CHECK && !check_app($exec_exec);
987 $exec = "$TERM_CMD $exec" if $term;
989 #sometimes kde workers forget the icons and the mini-icons:
990 if ( $mini_icon eq '' && $APPS_DIR eq $KDE_APPS) {
991 $mini_icon = "$exec_exec.xpm"
992 if ( -f "$KDE_MINI_ICONS$exec_exec.xpm");
993 $mini_icon = "$exec_exec.png"
994 if ( -f "$KDE3_MINI_ICONS$exec_exec.png");
995 $icon = "$exec_exec.xpm"
996 if ( -f "$KDE_ICONS$exec_exec.xpm" );
997 $icon = "$exec_exec.png"
998 if ( -f "$KDE3_ICONS$exec_exec.png" );
1002 #----------------------------
1003 # if no icons or ow and no style we can return now
1004 return($label, $dmicon{$flag . $which}, $exec)
1005 if ( ($law{"$flag$which"} eq 'ow'
1006 || $law{"$flag$which"} eq 'no'
1007 || !$MINI_ICONS) && !$STYLE );
1012 $mini_icon = $icon if ( $mini_icon eq '');
1013 $icon = $mini_icon if ( $icon eq '');
1017 # for mini-icons-tran && style(-tran) (we translate only the mini-icon
1018 # since gnome do not specify mini icon ...).
1019 if ( ($TRAN && $flag eq 'fvwm_') || ($TRAN_STYLE) ) {
1020 $tmp_icon = $mini_icon;
1021 if ( $tmp_icon =~ /\.png$/ ) {
1022 $tmp_icon =~ s/\.png$/\.xpm/;
1023 $tran_mini_icon = $tmp_icon if ( (-f "$TRAN_MINI_ICONS$tmp_icon")
1024 || !($TRAN_MINI_ICONS =~ /^\//) );
1025 $tran_icon = $tmp_icon if ( (-f "$TRAN_ICONS$tran_mini_icon")
1026 || !($TRAN_ICONS =~ /^\//) );
1031 # no .png icons with fvwm menu
1032 #$mini_icon = '' if ( $flag eq 'fvwm_' && $mini_icon =~ /\.png$/ );
1034 if ($check_mini_icons ne "" && $mini_icon ne "") {
1037 foreach $d (@check_mini_icons_path) {
1038 $ok = 1 if -f "$d/mini_icon";
1040 $mini_icon = "" if !$ok;
1042 if ($check_icons ne "" && $icon ne "") {
1045 foreach $d (@check_icons_path) {
1046 $ok = 1 if -f "$d/icon";
1051 # Ok the icons are computed except the path.
1054 if ( $STYLE && $which eq 'app' ) {
1055 if ( $tran_mini_icon ne '' ) {
1056 $style_mini_icon = $tran_mini_icon;
1058 $style_mini_icon = $mini_icon;
1060 if ( $tran_icon ne '' ) {
1061 $style_icon = $tran_icon
1064 $style_icon = $icon;
1066 update_style($style_mini_icon, $style_icon, $exec_exec)
1070 if ( $TRAN && $tran_mini_icon ne '' ) {
1071 $mini_icon = "$TRAN_MINI_ICONS$tran_mini_icon";
1072 } elsif ( $mini_icon ne '' ) {
1073 $mini_icon = "$MINI_ICONS_DIR$mini_icon";
1074 if ( $mini_icon =~ /\.png$/ ) { $mini_icon = "$PNG_ICONS$mini_icon" }
1075 else { $mini_icon = "$MINI_ICONS_DIR$mini_icon" }
1078 #return the info with icon
1080 return($label, $dmicon{$flag . $which}, $exec)
1081 if ( $law{"$flag$which"} eq 'ow'
1082 || $law{"$flag$which"} eq 'no'
1084 || ($mini_icon eq '' && $law{"$flag$which"} eq 're') );
1086 return($label, $mini_icon, $exec)
1087 if ($flag eq 'gtk_');
1090 "$place{\"$flag$which\"}$mini_icon$place{\"$flag$which\"}",$exec)
1091 if $mini_icon ne '';
1093 return($label, '', $exec);
1097 # ---------------------------------------------------------------------------
1101 my($style_mini_icon, $style_icon, $exec_exec) = @_;
1103 # Gnome exception for $exec_exec, I probably forget some ...
1104 # seems that there is a rule ...
1105 $exec_exec = 'GnomeTerminal' if ( $exec_exec eq 'gnome-terminal' );
1106 $exec_exec = 'Imlib Config Editor' if ( $exec_exec eq 'imlib_config' );
1107 $exec_exec = 'GnomeHelpBrowser' if ( $exec_exec eq 'gnome-help-browser' );
1108 $exec_exec = 'GQview' if ( $exec_exec eq 'gqview' );
1110 # kde exceptions. Some families of apps have the same name, class, resource
1111 # for windows manager, but kwm; (I try the caption and icon option with
1112 # kcminfo but do not succeed ...)
1113 # Anyway some of the concerned applications are kwm specifics.
1115 if ( $exec_exec eq 'kfmclient' ) {
1116 $style_icon = $style_mini_icon = 'kfm.xpm'; #kfm_home.xpm better ???
1120 $style_icon = $style_mini_icon = 'information_settings.xpm'
1121 if ( $exec_exec =~ /^kcminfo/ );
1122 $style_icon = $style_mini_icon = 'kcmkwm.xpm'
1123 if ( $exec_exec =~ /^kcmdisplay/ );
1124 $style_icon = $style_mini_icon = 'input_device_settings.xpm'
1125 if ( $exec_exec =~ /^kcminput/ );
1126 $style_icon = $style_mini_icon = 'kwm.xpm'
1127 if ( $exec_exec =~ /^kcmkwm/ );
1129 # Now we add the good path
1130 if ( $TRAN_STYLE || $TRAN ) {
1131 $style_mini_icon = "$TRAN_MINI_ICONS$style_mini_icon"
1132 if ( $style_mini_icon ne '');
1133 $style_icon = "$TRAN_ICONS$style_icon" if ( $style_icon ne '');
1135 $style_mini_icon = "$MINI_ICONS_DIR$style_mini_icon"
1136 if ( $style_mini_icon ne '' );
1137 $style_icon = "$ICONS_DIR$style_icon" if ( $style_icon ne '' );
1140 if (($style_mini_icon eq '' && $style_law eq 're') || ($style_law eq 'ow')) {
1141 $style_mini_icon = $dstyle{mini_icon};
1144 if (($style_icon eq '' && $style_law eq 're') || ($style_law eq 'ow')) {
1145 $style_icon = $dstyle{icon};
1148 # Update $STYLEOUTPUT
1149 if ( $style_mini_icon ne '' || $style_icon ne '' || $addstyle ne '' ) {
1150 $STYLEOUTPUT .= "Style \"$exec_exec\" MiniIcon " . "$style_mini_icon\n"
1151 if ( $style_mini_icon ne '' );
1152 $STYLEOUTPUT .= "Style \"$exec_exec\" Icon $style_icon\n"
1153 if ( $style_icon ne '' );
1154 $STYLEOUTPUT .= "Style \"$exec_exec\" $addstyle\n"
1155 if ( $addstyle ne '' );
1160 #--------------------------------------------------------------------------
1161 # Check if application binary is executable and reachable
1165 # If full path, dont use path, just check path
1166 if ( substr($app,0,1) eq '/' and -x $app ) { return 1 };
1167 # Check if an application is in the path
1168 foreach $dir (@PATH_DIRS) {
1169 if ( -x "$dir/$app" ) { return 1 }
1175 #----------------------------------------------------------------------------
1176 # Standard functions
1180 A perl script which parses gnome/kde menus definitions to build
1181 the corresponding fvwm/FvwmGtk menu. The script can also build
1182 Icon and MiniIcon style for the desktop applications.
1186 --help show this help and exit
1187 --version show version and exit
1188 --install-prefix DIR install prefix of the desktop
1189 --desktop NAME desktop to build the menu for it:
1190 gnome-sys (default), gnome-user, gnome-redhat, gnome-madriva,
1192 --type NAME fvwm (default) or gtk for a FvwmGtk menu
1193 --fvwmgtk-alias NAME FvwmGtk module name, default is FvwmGtk
1194 --title NAME menu title, default depends on --desktop
1195 --name NAME menu name, default depends on --desktop
1196 --merge-user-menu merge the system menu with the user menu
1197 --enable-mini-icons enable mini-icons in menu
1198 --enable-tran-mini-icons enable mini-icons in menu and
1199 translation of foo.png icon names to foo.xpm
1200 --mini-icons-path DIR path of menus icons (relative to your
1201 ImagePath), default is 'mini/'
1202 --png-icons-path DIR path of .png icons, default is your ImagePath
1203 --tran-mini-icons-path DIR path of menus icons for translation
1204 --check-mini-icons PATH check if the mini icons are in PATH
1205 --icon-toptitle micon:law:place:sidepic:color mini-icon for the top
1206 title and sidepic for the top menu
1207 --icon-title micon:law:place:sidepic:color as above for sub menus
1208 --icon-folder micon:law:place mini-icons for folder item
1209 --icon-app micon:law:place mini-icon for applications item
1210 --wm-icons define menu icon names to use with wm-icons
1211 --enable-style build icons and mini-icons style
1212 --enable-tran-style as above with translation (for FvwmGtk menus)
1213 --icon-style micon:icon:law icons for style
1214 --icons-path DIR define the directory of the icons,
1215 the default is very good
1216 --tran-icons-path DIR similar to the above option.
1217 --check-icons PATH check if the icons are in the PATH
1218 --submenu-name-prefix NAME in general not useful
1219 --dir DIR use path as desktop menu description
1220 --destroy-type FLAG how to destroy menu, valid values:
1221 'yes', 'no', 'dynamic', the default depends on --type
1222 --xterm CMD complete terminal command to run applications
1223 in it, default is 'xterm -e'
1224 --lang NAME language, default is \$LANG
1225 --utf8 For desktop entries coded in UTF-8 (KDE2)
1226 --uniconv Use (un)iconv for UTF-8 translation
1227 --uniconv-exec uniconv or iconv (default)
1228 --menu-style name assign specified MenuStyle name to menus
1229 --[no]check-app [do not] check that apps are in your path
1230 --time-limit NUM limit script running time to NUM seconds
1231 Short options are ok if not ambiguous: -h, -x, -icon-a.
1242 print STDERR "Try '$0 --help' for more information.\n";