#!/usr/bin/perl

# Copyright (c) 1999-2009 Mikhael Goikhman
#
# 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, see: <http://www.gnu.org/licenses/>

# Filter this script to pod2man to get a man page:
#   pod2man -c "Fvwm Utilities" fvwm-menu-xlock | nroff -man | less -e

use Getopt::Long;

my $version = "1.0.8";

my $name  = 'XLockMenu';
my $title = 'XLock Modes';
my $itemf = '%n\t(%d)';  # may contain %n, %d, %D.
my $icont = '';
my $iconi = '';
my $wm_icons = 0;
my $special_first = 0;

GetOptions(
	"help|h|?"  => \&show_help,
	"version|V" => \&show_version,
	"name=s"    => \$name,
	"title=s"   => \$title,
	"item=s"    => \$itemf,
	"icon-title=s"  => \$icont,
	"icon-item=s"   => \$iconi,
	"wm-icons"      => \$wm_icons,
	"special-first" => \$special_first,
) || wrong_usage();

if ($wm_icons) {
	$icont ||= "";
	$iconi ||= "menu/lock.xpm";
}

my $icont_str = $icont ? "%$icont%" : "";
my $iconi_str = $iconi ? "%$iconi%" : "";
my $params = @ARGV ? ' ' . join(' ', @ARGV) : '';
my $lines1 = "";  # non-special mode lines
my $lines2 = "";  # special mode lines

my $start = 0;
my $special = 0;
$itemf =~ s/\\t/\t/g;
open(XL, "xlock -display NONE -help 2>&1 |")
	|| die "Exec echo 'Could not run xlock'\n";

print "DestroyMenu $name\n";
print "AddToMenu $name \"$icont_str$title\" Title\n";

while (<XL>) {
	chomp;

	/where mode is one of:/ && do {
		$start = 1;
		next;
	};
	if ($start && $_) {
		my ($misc, $name, $dsc) = split(/\s+/, $_, 3);
		next if $name =~ /^-/;
		my $dsc2 = $dsc =~ /^Shows (.*)$/ ? $1 : $dsc;
		my $item_str = $itemf;
		$item_str =~ s/\\t/\t/g;
		&expand_width_specifier(\$item_str, 'n', $name);
		&expand_width_specifier(\$item_str, 'd', $dsc);
		&expand_width_specifier(\$item_str, 'D', $dsc2);

		$special = 1 if !$special && $name eq 'blank';
		($special ? $lines2 : $lines1) .=
			qq(+ "$iconi_str$item_str" Exec xlock$params -mode $name\n);
	}
}

close XL;
print $special_first
	? qq($lines2+ "" Nop\n$lines1)
	: qq($lines1+ "" Nop\n$lines2);

exit(0);

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

# Substitutes all %N1*N2x in $name by properly stripped and justified $value.
sub expand_width_specifier (\$$$) {
	my ($name, $char, $value) = @_;
	$$name =~ s/%(-?\d+)?(\*(-?)(\d+))?$char/
		my $value = !$2 || $4 <= 3 || $4 > length($value) ? $value : $3
			? "..." . substr($value, -$4 + 3, $4 - 3)
			: substr($value, 0, $4 - 3) . "...";
		$1? sprintf("%$1s", $value): $value;
	/ge;
}

sub show_help {
	print "A small perl script which builds xlock menu for fvwm.\n\n";
	print "Usage: $0 [OPTIONS] [-- XLOCK-OPTIONS]\n";
	print "Options:\n";
	print "\t--help           show this help and exit\n";
	print "\t--version        show the version and exit\n";
	print "\t--name=NAME      menu name,  default is '$name'\n";
	print "\t--title=NAME     menu title, default is '$title'\n";
	print "\t--item=NAME      menu item format, default is '$itemf'\n";
	print "\t--icon-title=XPM menu title icon, default is no\n";
	print "\t--icon-item=XPM  menu item  icon, default is no\n";
	print "\t--wm-icons       define icon names to use with wm-icons\n";
	print "\t--special-first  put special modes first\n";
	print "Short options are ok if not ambiguous: -h, -t.\n";
	print "\nSome useful xlock(1) options, 'xlock -h' for more:\n";
	print "\t-delay usecs     delay between batches of animations\n";
	print "\t-nolock          screensaver, don't lock the display\n";
	print "\t-inwindow        run in window as opposite to -inroot\n";
	print "\t-sound           turn on sound if enabled\n";
	print "\t-nice level      decrease the process priority (0 .. 19)\n";
	exit 0;
}

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

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

__END__

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

=head1 NAME

fvwm-menu-xlock - builds xlock menu definition for fvwm

=head1 SYNOPSIS

B<fvwm-menu-xlock>
[ B<--help>|B<-h>|B<-?> ]
[ B<--version>|B<-V> ]
[ B<--name>|B<-n> name ]
[ B<--title>|B<-t> title ]
[ B<--item> format ]
[ B<--icon-title> icon ]
[ B<--icon-item> icon ]
[ B<--special-first>|B<-s> ]
[ -- xlock params ]

=head1 DESCRIPTION

A simple perl script which parses xlock's output to build an fvwm
menu definition of all xlock's modes.

=head1 OPTIONS

=over 4

=item B<--help>

show the help and exit

=item B<--version>

show the version and exit

=item B<--name> name

define menu name in the following argument.
Default is "XLockMenu"

=item B<--title> title

define menu title in the following argument.
Default is "XLock Modes".

=item B<--item> format

define menu item format in the following argument,
default is '%n\t(%d)'.
TAB can be specified as '\t', but in .fvwm2rc you should specify a double
backslash or a real TAB.

Format specifiers:

  %n - mode name
  %d - mode description
  %D - mode description without "Shows " prefix if any

These specifiers can receive an optional integer size, positive for right
adjusted string or negative for left adjusted, example: %8x; and optional
*num or *-num, which means to leave only the first or last (if minus) num of
chars, the num must be greater than 3, since the striped part is replaced
with "...", example: %*30x. Both can be combined: %-10*-20x, this instructs to
get only the 20 last characters, but if the length is less then 10 - to fill
with up to 10 spaces on the right.

=item B<--icon-title> icon

=item B<--icon-item> icon

define menu icon for title and regular item accordingly.
Default is no menu icons (equivalent to an empty icon argument).

=item B<--wm-icons>

define icon names suitable for use with wm-icons package.
Currently this is equivalent to: --icon-title '' --icon-item
menu/lock.xpm.

=item B<--special-first>

instructs to include special modes (usually black, bomb and random) first.

=back

Option parameters can be specified either using '=' or in the next argument.
Short options are ok if not ambiguous: -h, -t; but be careful with
short options, what is now unambiguous, can became ambiguous in the next
versions.

Additional arguments (after B<-->) will be passed to xlock.

Please see the B<xlock>(1) man page for the xlock options.

=head1 USAGE

Add these lines to your fvwm configuration file:

  PipeRead 'fvwm-menu-xlock --name MenuSSaver --title "Screensaver" \
    --icon-item mini-bball.xpm --special-first -- -nice 19 -nolock'
  PipeRead 'fvwm-menu-xlock --name MenuSLock --title "Lock Screen" \
    --icon-item mini-rball.xpm --special-first -- -nice 19'
  AddToMenu "Utilities" "Screensaver%mini-monitor.xpm%" Popup MenuSSaver
  AddToMenu "Utilities" "Screenlock%mini-lock.xpm%"     Popup MenuSLock

=head1 AUTHORS

Charles K. Hines <chuck_hines@vnet.ibm.com>, initial version.

Mikhael Goikhman <migo@homemail.com>, from 24 Feb 1999.

=head1 COPYING

The script is distributed by the same terms as fvwm itself.
See GNU General Public License for details.

=head1 BUGS

Depends on the output of xlock. Will produce an empty menu if the structure
of the output is changed.

=cut

# ***************************************************************************
