#!/usr/bin/perl
#-----------------------------------------------------------------------------
#	$Id : odfhighlight 0.2 2008-05-04 JMG$
#-----------------------------------------------------------------------------

=head1	NAME

odfhighlight - search, replace and highlight text in a document

=head1	SYNOPSIS

odfhighlight "source.odt" "search string" -r "replacement" -o "target.odt"

replaces "search string" by "replacement" in the file "source.odt", highlights
each replacement with a yellow (default) backgound, then writes the resulting
document as "target.odt"

odfhighlight "myfile.odt" "search string" -color "green"

highlights each occurrence of "search string" in "myfile.sxw" with a green
background color, without changing the text (without "-o" option, the changes
apply to "myfile.odt"

=head1	ARGUMENTS AND OPTIONS

=head2	Default behaviour

With the "minimal" command line, with only a filename and a string as
arguments, each matching string is highlighted with a yellow background
and represented with the "Standard" style.

=head2	Options

	-e --encoding "xxxxxx"

		character set to use, if different from the default
		
	-r --replacement "new string"

		"new string" is used as a replacement for "search string"

	-c --color "code"

		an RGB color code, expressed either as the concatenation of
		3 comma-separated decimal values (each one in the range
		0..255, ex: "72,61,139" for a dark slate blue), or a 6-digit
		hexadecimal number, preceded by a "#" (ex: #00ff00 for green)
		or, if a colormap is available and known in your
		OpenOffice::OODoc installation, a symbolic color name (ex:
		"sky blue")

	-s --stylename "name"

		the name of the color style (default: "MyHighlight"); the
		user must provide a style name that is not already in use
		in the document

	-p --property "property=value"

		This option can be repeated; each occurrence gives an
		additional property for the highlight style (font name, size,
		foreground color, ...). For example, with the combination of
		-p 'fo:color=#ff0000' and -p 'fo:font-size=18pt', the
		highlighted text will be made of 18pt-sized, red characters.
		In order to master these options, you should have some
		knowledge of the Form Objects (FO) vocabulary that is used
		in the OpenDocument specification.
	
	-o --output "filename"
	-t --target "filename"

		an alternative filename to save the modified document, when
		the source document must remain unchanged

=cut


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

use OpenOffice::OODoc	2.101;
use Getopt::Long;

#-----------------------------------------------------------------------------
# getting the arguments and options

my $encoding		= $OpenOffice::OODoc::XPath::LOCAL_CHARSET;
my $target		= undef;
my $replace		= undef;
my $color		= '#ffff00'; # yellow
my $stylename		= 'MyHighLight';
my %properties		= ();

GetOptions
	(
	'encoding=s'		=> \$encoding,
	'replacement=s'		=> \$replace,
	'color=s'		=> \$color,
	'stylename=s'		=> \$stylename,
	'property=s'		=> \%properties,
	'output|target=s'	=> \$target
	);

$color	= odfColor($color) or die "Color code is not valid\n";

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

my $filename	= $ARGV[0];
my $search	= $ARGV[1];
die "usage: oohighlight <file> <search_string> [-options]\n"
	unless ($filename && $search);

#-----------------------------------------------------------------------------
# opening the document

my $doc		= odfDocument
			(
			file		=> $filename,
			local_encoding	=> $encoding
			)
	or die "File unavailable or non-ODF file\n";

#-----------------------------------------------------------------------------
# creating the highlight style

my $attr = $doc->{'opendocument'} ?
		'fo:background-color' : 'style:text-background-color';
$properties{$attr} = $color;

$doc->createStyle
	(
	$stylename,
	family		=> 'text',
	properties	=> { %properties }
	)
	or die "Please choose another style name.\n";
	
#-----------------------------------------------------------------------------
# searching and replacing

my @list = $doc->selectElementsByContent($search, $replace);

#-----------------------------------------------------------------------------
# coloring

if (defined $replace)
	{
		# just in order to avoid unneeded metacharacter processing
	$replace =~ s/([\\\(\)\.\*\?\[\]\|\-])/\\$1/g;
	$search	= $replace;
	}

foreach my $element (@list)
	{
	$doc->setSpan($element, $search, $stylename);
	}

#-----------------------------------------------------------------------------
# saving the result

$doc->save($target);
exit;

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