ODF-lpOD_Helper
view release on metacpan or search on metacpan
lib/ODF/lpOD_Helper.pm view on Meta::CPAN
=head2 $boolean = $elt->His_text_container()
Returns TRUE if C<$elt> is a paragraph, heading or span.
=head2 $newelt = $elt->Hsplit_element_at($offset)
C<Hsplit_element_at> is like XML::Twig's C<split_at> but also knows how
to split text:s nodes.
If C<$elt> is a textual leaf (PCDATA, text:s, etc.) it is split, otherwise
it's first textual child is split. Even a single-character leaf may be "split"
if $offset==0 or 1, see below.
The "right half" is moved to a new next sibling node, which is returned.
$offset must be between 0 and the existing length, inclusive.
If $offset is 0 then all existing content is moved to the new sibling
and the original node will be empty upon return.
if $offset equals the existing length then the new sibling will be empty.
If a text:s node is split then the new node will also be a text:s node
"containing" the appropriate number of spaces. The 'text:c' attribute will
be zero if the node is "empty".
If a text:tab or text:line-break node is split then if $offset==0 the new node
will be an empty PCDATA node,
or if $offset==1 the original will be transmuted in-place to become
an empty PCDATA node.
=cut
sub ODF::lpOD::Element::His_textual {
my $elt = shift;
$elt->passes(TEXTLEAF_FILTER)
}
sub ODF::lpOD::Element::His_text_container {
my $elt = shift;
$elt->passes(TEXTCONTAINER_FILTER)
}
sub ODF::lpOD::Element::Hsplit_element_at {
my ($elt, $offset) = @_;
confess "Wrong number of arguments" unless @_==2;
# see XML::Twig::split_at
my $text_elt= $elt->His_textual() ? $elt
: $elt->first_child(TEXTLEAF_FILTER)
|| confess("no textual leaf found");
if ($text_elt->tag eq 'text:s') {
my $existing_count = $text_elt->get_attribute('c') // 1;
my $right_count = $existing_count - $offset;
confess ivis 'offset $offset exceeds existing text:s count($existing_count)'
if $right_count < 0;
$text_elt->set_attribute('c', $offset); # possibly zero
my $result = $text_elt->insert_element("text:s", position => NEXT_SIBLING);
$result->set_attribute('c', $right_count); # possibly zero
return $result
}
elsif ($text_elt->tag eq '#PCDATA') {
my $existing_len = length($text_elt->text);
confess ivis 'offset $offset exceeds existing pcdata length ($existing_len)'
if $offset > $existing_len;
return $text_elt->split_at($offset);
}
elsif ($offset == 0) {
#my $para = $elt->passes(PARA_FILTER) ? $elt : $elt->parent(PARA_FILTER);
#btw dvis 'BEFORE TRANSMUTE $para = ',fmt_tree($para);
#btw dvis 'BEFORE TRANSMUTE $elt = ',fmt_tree($elt);
my $result =
$text_elt->insert_element($text_elt->clone, position => NEXT_SIBLING);
#btw dvis '$result ',fmt_tree($result);
# *TRANSMUTE* the original node to an empty PCDATA node
$text_elt->del_atts();
if (defined $text_elt->atts) {
delete($text_elt->{att}) // oops; # Peeking into XML::Twig internals!
}
my @unhandled = grep{
! /^(?:next_|prev_|first_|last_|parent|gi|empty|former)/
} keys %$text_elt;
oops "unhandled left-over member(s) @unhandled" if @unhandled;
$text_elt->set_tag("#PCDATA");
# unpleasantly looking into ODF::lpOD internals...
my $class = $ODF::lpOD::Element::CLASS{'#PCDATA'} // oops;
bless $text_elt, $class;
$text_elt->set_text("");
return $result;
}
elsif ($offset == 1) {
my $result = $text_elt->insert_element('#PCDATA', position=>NEXT_SIBLING);
$result->set_text(""); # unnecessary?
return $result;
}
else {
confess "Hsplit_element_at : invocant $elt has no textual leaf"
}
}# Hsplit_element_at
=head2 $context->Hget_text()
=head2 $context->Hget_text(prune_cond => COND)
Gets the combined "virtual text" in or below C<$context>,
by default including in nested paragraphs (e.g. in Frames or Tables).
The special nodes which represent tabs, line-breaks and
consecutive spaces are expanded to the corresponding characters.
Option B<prune_cond> may be used to omit text below specified node types
(see C<Hnext_elt>).
=head3 B<Note>
C<ODF::lpOD::TextElement::get_text()> with option I<recursive -E<gt> TRUE>
looks like it should do the same thing as C<Hget_text()>, but it has bugs:
=over 4
=item 1.
The special nodes for tab, etc. are expanded only when they are the
immediate children of $context. With the 'recursive'
option #PCDATA nodes in nested paragraphs are expanded but tabs, etc.
( run in 1.438 second using v1.01-cache-2.11-cpan-995e09ba956 )