| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | package Text::Autoformat; | 
| 2 |  |  |  |  |  |  | $Text::Autoformat::VERSION = '1.73'; | 
| 3 | 4 |  |  | 4 |  | 64332 | use 5.006; | 
|  | 4 |  |  |  |  | 15 |  | 
| 4 | 4 |  |  | 4 |  | 19 | use strict; | 
|  | 4 |  |  |  |  | 7 |  | 
|  | 4 |  |  |  |  | 123 |  | 
| 5 | 4 |  |  | 4 |  | 20 | use warnings; | 
|  | 4 |  |  |  |  | 11 |  | 
|  | 4 |  |  |  |  | 115 |  | 
| 6 | 4 |  |  | 4 |  | 19 | use Carp; | 
|  | 4 |  |  |  |  | 5 |  | 
|  | 4 |  |  |  |  | 404 |  | 
| 7 |  |  |  |  |  |  |  | 
| 8 |  |  |  |  |  |  | require Exporter; | 
| 9 |  |  |  |  |  |  |  | 
| 10 | 4 |  |  | 4 |  | 4044 | use Text::Reform qw( form tag break_at break_with break_wrap break_TeX ); | 
|  | 4 |  |  |  |  | 30070 |  | 
|  | 4 |  |  |  |  | 28 |  | 
| 11 | 4 |  |  | 4 |  | 3195 | use Text::Autoformat::Hang; | 
|  | 4 |  |  |  |  | 11 |  | 
|  | 4 |  |  |  |  | 135 |  | 
| 12 | 4 |  |  | 4 |  | 2252 | use Text::Autoformat::NullHang; | 
|  | 4 |  |  |  |  | 10 |  | 
|  | 4 |  |  |  |  | 2690 |  | 
| 13 |  |  |  |  |  |  |  | 
| 14 |  |  |  |  |  |  | our @ISA = qw(Exporter); | 
| 15 |  |  |  |  |  |  | our @EXPORT = qw( autoformat ); | 
| 16 |  |  |  |  |  |  | our @EXPORT_OK = | 
| 17 |  |  |  |  |  |  | qw( form tag break_at break_with break_wrap break_TeX ignore_headers ); | 
| 18 |  |  |  |  |  |  |  | 
| 19 |  |  |  |  |  |  |  | 
| 20 |  |  |  |  |  |  | my %std_highlight_ignore = map {$_=>1} qw { | 
| 21 |  |  |  |  |  |  | a an at as and are | 
| 22 |  |  |  |  |  |  | but by | 
| 23 |  |  |  |  |  |  | ere | 
| 24 |  |  |  |  |  |  | for from | 
| 25 |  |  |  |  |  |  | in into is | 
| 26 |  |  |  |  |  |  | of on onto or over | 
| 27 |  |  |  |  |  |  | per | 
| 28 |  |  |  |  |  |  | the to that than | 
| 29 |  |  |  |  |  |  | until unto upon | 
| 30 |  |  |  |  |  |  | via | 
| 31 |  |  |  |  |  |  | with while whilst within without | 
| 32 |  |  |  |  |  |  | }; | 
| 33 |  |  |  |  |  |  |  | 
| 34 |  |  |  |  |  |  | my $STD_HIGHLIGHT_IGNORES = sub { | 
| 35 |  |  |  |  |  |  | my ($word) = @_; | 
| 36 |  |  |  |  |  |  | return $std_highlight_ignore{lc $word} ? recase($word,'lower') : recase($word,'title'); | 
| 37 |  |  |  |  |  |  | }; | 
| 38 |  |  |  |  |  |  |  | 
| 39 |  |  |  |  |  |  | my @entities = qw { | 
| 40 |  |  |  |  |  |  | Á   á      Â    â        Æ    æ | 
| 41 |  |  |  |  |  |  | À   à      Α    α        Ã   ã | 
| 42 |  |  |  |  |  |  | Ä     ä        Β     β         Ç   ç | 
| 43 |  |  |  |  |  |  | Χ      χ         Δ    δ        É   é | 
| 44 |  |  |  |  |  |  | Ê    ê       È   è       Ε  ε | 
| 45 |  |  |  |  |  |  | Η      η         Ð      ð          Ë     ë | 
| 46 |  |  |  |  |  |  | Γ    γ       Í   í       Î    î | 
| 47 |  |  |  |  |  |  | Ì   ì      Ι     ι         Ï     ï | 
| 48 |  |  |  |  |  |  | Κ    κ       Λ   λ       Μ       μ | 
| 49 |  |  |  |  |  |  | Ñ   ñ      Ν       ν           Ó   ó | 
| 50 |  |  |  |  |  |  | Ô    ô       Œ    œ        Ò   ò | 
| 51 |  |  |  |  |  |  | Ω    ω       Ο  ο      Õ   õ | 
| 52 |  |  |  |  |  |  | Ö     ö        Φ      φ          Π       π | 
| 53 |  |  |  |  |  |  | ″    ′       Ψ      ψ          Ρ      ρ | 
| 54 |  |  |  |  |  |  | Š   š      Σ    σ        Τ      τ | 
| 55 |  |  |  |  |  |  | Θ    θ       Þ    þ        Ú   ú | 
| 56 |  |  |  |  |  |  | Û    û       Ù   ù       Υ  υ | 
| 57 |  |  |  |  |  |  | Ü     ü        Ξ       ξ           Ý   ý | 
| 58 |  |  |  |  |  |  | Ÿ     ÿ        Ζ     ζ | 
| 59 |  |  |  |  |  |  | }; | 
| 60 |  |  |  |  |  |  |  | 
| 61 |  |  |  |  |  |  | my %lower_entities = @entities; | 
| 62 |  |  |  |  |  |  | my %upper_entities = reverse @entities; | 
| 63 |  |  |  |  |  |  |  | 
| 64 |  |  |  |  |  |  | my %casing = ( | 
| 65 |  |  |  |  |  |  | lower => [ \%lower_entities,  \%lower_entities, | 
| 66 |  |  |  |  |  |  | sub { $_ = lc },   sub { $_ = lc } ], | 
| 67 |  |  |  |  |  |  | upper => [ \%upper_entities,  \%upper_entities, | 
| 68 |  |  |  |  |  |  | sub { $_ = uc },   sub { $_ = uc } ], | 
| 69 |  |  |  |  |  |  | title => [ \%upper_entities,  \%lower_entities, | 
| 70 |  |  |  |  |  |  | sub { $_ = ucfirst lc }, sub { $_ = lc } ], | 
| 71 |  |  |  |  |  |  | ); | 
| 72 |  |  |  |  |  |  |  | 
| 73 |  |  |  |  |  |  | my $default_margin = 72; | 
| 74 |  |  |  |  |  |  | my $default_widow  = 10; | 
| 75 |  |  |  |  |  |  |  | 
| 76 |  |  |  |  |  |  | $Text::Autoformat::widow_slack = 0.1; | 
| 77 |  |  |  |  |  |  |  | 
| 78 |  |  |  |  |  |  |  | 
| 79 |  |  |  |  |  |  | sub defn($) | 
| 80 |  |  |  |  |  |  | { | 
| 81 | 130 | 50 |  | 130 | 0 | 541 | return $_[0] if defined $_[0]; | 
| 82 | 0 |  |  |  |  | 0 | return ""; | 
| 83 |  |  |  |  |  |  | } | 
| 84 |  |  |  |  |  |  |  | 
| 85 |  |  |  |  |  |  | my $ignore_headers = qr/ | 
| 86 |  |  |  |  |  |  | \A | 
| 87 |  |  |  |  |  |  | (?: From \b .* $)? | 
| 88 |  |  |  |  |  |  | (?: [^:\n]+ : .* \n | 
| 89 |  |  |  |  |  |  | (?: [ \t] .* \n)* | 
| 90 |  |  |  |  |  |  | )+ | 
| 91 |  |  |  |  |  |  | \s* | 
| 92 |  |  |  |  |  |  | \Z | 
| 93 |  |  |  |  |  |  | /mx; | 
| 94 |  |  |  |  |  |  | my $ignore_indent  = qr/^[^\S\n].*(\n[^\S\n].*)*$/; | 
| 95 |  |  |  |  |  |  |  | 
| 96 | 6 | 100 |  | 6 | 0 | 43 | sub ignore_headers { $_[0] && /$ignore_headers/ } | 
| 97 |  |  |  |  |  |  |  | 
| 98 |  |  |  |  |  |  | # BITS OF A TEXT LINE | 
| 99 |  |  |  |  |  |  |  | 
| 100 |  |  |  |  |  |  | my $quotechar = qq{[!#%=|:;]}; | 
| 101 |  |  |  |  |  |  | my $quotechunk = qq{(?:$quotechar(?![a-z])|(?:[a-z]\\w*)?>+)}; | 
| 102 |  |  |  |  |  |  | my $QUOTER = qq{(?:(?i)(?:$quotechunk(?:[ \\t]*$quotechunk)*))}; | 
| 103 |  |  |  |  |  |  |  | 
| 104 |  |  |  |  |  |  | my $separator = q/(?:[-_]{2,}|[=#*]{3,}|[+~]{4,})/; | 
| 105 |  |  |  |  |  |  |  | 
| 106 | 4 |  |  | 4 |  | 6626 | use overload; | 
|  | 4 |  |  |  |  | 4815 |  | 
|  | 4 |  |  |  |  | 29 |  | 
| 107 |  |  |  |  |  |  | sub autoformat  # ($text, %args) | 
| 108 |  |  |  |  |  |  | { | 
| 109 | 4 |  |  | 4 | 0 | 917 | my ($text,%args,$toSTDOUT); | 
| 110 |  |  |  |  |  |  |  | 
| 111 | 4 |  |  |  |  | 13 | foreach ( @_ ) | 
| 112 |  |  |  |  |  |  | { | 
| 113 | 7 | 100 | 33 |  |  | 51 | if (ref eq 'HASH') | 
|  |  | 50 | 33 |  |  |  |  | 
| 114 | 3 |  |  |  |  | 17 | { %args = (%args, %$_) } | 
| 115 |  |  |  |  |  |  | elsif (!defined($text) && !ref || overload::Method($_,'""')) | 
| 116 | 4 |  |  |  |  | 13 | { $text = "$_" } | 
| 117 |  |  |  |  |  |  | else { | 
| 118 | 0 |  |  |  |  | 0 | croak q{Usage: autoformat([text],[{options}])} | 
| 119 |  |  |  |  |  |  | } | 
| 120 |  |  |  |  |  |  | } | 
| 121 |  |  |  |  |  |  |  | 
| 122 | 4 | 50 |  |  |  | 20 | unless (defined $text) { | 
| 123 | 0 |  |  |  |  | 0 | $text = join("",); | 
| 124 | 0 |  |  |  |  | 0 | $toSTDOUT = !defined wantarray(); | 
| 125 |  |  |  |  |  |  | } | 
| 126 |  |  |  |  |  |  |  | 
| 127 | 4 | 100 |  |  |  | 23 | return $text unless $text =~ /\S/; | 
| 128 |  |  |  |  |  |  |  | 
| 129 | 3 | 100 |  |  |  | 12 | $args{right}   = $default_margin unless exists $args{right}; | 
| 130 | 3 | 50 |  |  |  | 13 | $args{justify} = "" unless exists $args{justify}; | 
| 131 | 3 | 50 | 50 |  |  | 23 | $args{widow}   = 0 if ($args{justify}||"") =~ /full/; | 
| 132 | 3 | 50 |  |  |  | 12 | $args{widow}   = $default_widow unless exists $args{widow}; | 
| 133 | 3 | 50 |  |  |  | 12 | $args{case}    = '' unless exists $args{case}; | 
| 134 | 3 | 100 |  |  |  | 11 | $args{lists}   = 1 unless exists $args{lists}; | 
| 135 | 3 | 50 |  |  |  | 11 | $args{squeeze} = 1 unless exists $args{squeeze}; | 
| 136 | 3 | 50 |  |  |  | 12 | $args{gap}     = 0 unless exists $args{gap}; | 
| 137 | 3 | 50 |  |  |  | 22 | $args{break}  = break_at('-') unless exists $args{break}; | 
| 138 | 3 |  |  |  |  | 47 | $args{impfill} = ! exists $args{fill}; | 
| 139 | 3 |  |  |  |  | 7 | $args{expfill} = $args{fill}; | 
| 140 | 3 | 50 |  |  |  | 13 | $args{tabspace} = 8 unless exists $args{tabspace}; | 
| 141 | 3 | 50 |  |  |  | 10 | $args{renumber} = 1 unless exists $args{renumber}; | 
| 142 | 3 | 50 |  |  |  | 12 | $args{autocentre} = 1 unless exists $args{autocentre}; | 
| 143 | 3 | 50 |  |  |  | 10 | $args{_centred} = 1 if $args{justify} =~ /cent(er(ed)?|red?)/; | 
| 144 | 3 |  | 100 |  |  | 20 | $args{all} ||= $args{mail}; | 
| 145 |  |  |  |  |  |  |  | 
| 146 |  |  |  |  |  |  | # SPECIAL IGNORANCE... | 
| 147 | 3 | 100 |  |  |  | 7 | if ($args{ignore}) { | 
| 148 | 2 |  |  |  |  | 4 | $args{all} = 1; | 
| 149 | 2 |  |  |  |  | 6 | $args{ignore} = _build_ignore( $args{ignore} ); | 
| 150 |  |  |  |  |  |  | } | 
| 151 |  |  |  |  |  |  | else { | 
| 152 | 1 |  |  | 1 |  | 5 | $args{ignore} = sub{0}; | 
|  | 1 |  |  |  |  | 2 |  | 
| 153 |  |  |  |  |  |  | } | 
| 154 |  |  |  |  |  |  |  | 
| 155 | 3 | 100 |  |  |  | 10 | if ( $args{mail} ) { | 
| 156 | 1 |  |  |  |  | 2 | my $ignore = $args{ignore}; | 
| 157 | 1 | 100 |  | 7 |  | 4 | $args{ignore} = sub { $ignore->(@_) || ignore_headers(@_) }; | 
|  | 7 |  |  |  |  | 16 |  | 
| 158 |  |  |  |  |  |  | } | 
| 159 |  |  |  |  |  |  |  | 
| 160 |  |  |  |  |  |  | # DETABIFY | 
| 161 | 3 |  |  |  |  | 27 | my @rawlines = split /\n/, $text; | 
| 162 | 4 |  |  | 4 |  | 5660 | use Text::Tabs; $tabstop = $args{tabspace}; | 
|  | 4 |  |  |  |  | 3249 |  | 
|  | 4 |  |  |  |  | 16654 |  | 
|  | 3 |  |  |  |  | 8 |  | 
| 163 | 3 |  |  |  |  | 15 | @rawlines = expand(@rawlines); | 
| 164 |  |  |  |  |  |  |  | 
| 165 |  |  |  |  |  |  | # HANDLE QUOTING CHANGE | 
| 166 | 3 | 50 |  |  |  | 189 | my $quoter = exists $args{quoter} ? $args{quoter} : $QUOTER; | 
| 167 | 3 |  |  |  |  | 9 | $quoter =~ s//$QUOTER/g; | 
| 168 |  |  |  |  |  |  |  | 
| 169 |  |  |  |  |  |  | # PARSE EACH LINE | 
| 170 |  |  |  |  |  |  |  | 
| 171 | 3 |  |  |  |  | 4 | my $pre = 0; | 
| 172 | 3 |  |  |  |  | 5 | my @lines; | 
| 173 | 3 |  |  |  |  | 8 | foreach (@rawlines) | 
| 174 |  |  |  |  |  |  | { | 
| 175 | 26 |  |  |  |  | 78 | push @lines, { raw     => $_ }; | 
| 176 | 26 | 50 |  |  |  | 453 | s/\A([ \t]*)($quoter?)([ \t]*)// | 
| 177 |  |  |  |  |  |  | or die "Internal Error ($@) on '$_'"; | 
| 178 | 26 |  |  |  |  | 65 | $lines[-1]{presig} =  $lines[-1]{prespace}   = defn $1; | 
| 179 | 26 |  |  |  |  | 57 | $lines[-1]{presig} .= $lines[-1]{quoter}     = defn $2; | 
| 180 | 26 |  |  |  |  | 54 | $lines[-1]{presig} .= $lines[-1]{quotespace} = defn $3; | 
| 181 |  |  |  |  |  |  |  | 
| 182 | 26 |  |  |  |  | 106 | $lines[-1]{hang} = Text::Autoformat::Hang->new($_, $args{lists}); | 
| 183 |  |  |  |  |  |  |  | 
| 184 | 26 | 50 |  |  |  | 234 | s/([ \t]*)(.*?)(\s*)$// | 
| 185 |  |  |  |  |  |  | or die "Internal Error ($@) on '$_'"; | 
| 186 | 26 |  |  |  |  | 90 | $lines[-1]{hangspace} = defn $1; | 
| 187 | 26 |  |  |  |  | 47 | $lines[-1]{text} = defn $2; | 
| 188 | 26 |  | 66 |  |  | 85 | $lines[-1]{empty} = $lines[-1]{hang}->empty() && $2 !~ /\S/; | 
| 189 | 26 |  |  |  |  | 190 | $lines[-1]{separator} = $lines[-1]{text} =~ /^$separator$/; | 
| 190 |  |  |  |  |  |  | } | 
| 191 |  |  |  |  |  |  |  | 
| 192 |  |  |  |  |  |  | # SUBDIVIDE DOCUMENT INTO COHERENT SUBSECTIONS | 
| 193 |  |  |  |  |  |  |  | 
| 194 | 3 |  |  |  |  | 6 | my @chunks; | 
| 195 | 3 |  |  |  |  | 8 | push @chunks, [shift @lines]; | 
| 196 | 3 |  |  |  |  | 8 | foreach my $line (@lines) | 
| 197 |  |  |  |  |  |  | { | 
| 198 | 23 | 100 | 33 |  |  | 179 | if ($line->{separator} || | 
|  |  |  | 33 |  |  |  |  | 
|  |  |  | 33 |  |  |  |  | 
|  |  |  | 66 |  |  |  |  | 
| 199 |  |  |  |  |  |  | $line->{quoter} ne $chunks[-1][-1]->{quoter} || | 
| 200 |  |  |  |  |  |  | $line->{empty} || | 
| 201 |  |  |  |  |  |  | @chunks && $chunks[-1][-1]->{empty}) | 
| 202 |  |  |  |  |  |  | { | 
| 203 | 10 |  |  |  |  | 24 | push @chunks, [$line]; | 
| 204 |  |  |  |  |  |  | } | 
| 205 |  |  |  |  |  |  | else | 
| 206 |  |  |  |  |  |  | { | 
| 207 | 13 |  |  |  |  | 16 | push @{$chunks[-1]}, $line; | 
|  | 13 |  |  |  |  | 30 |  | 
| 208 |  |  |  |  |  |  | } | 
| 209 |  |  |  |  |  |  | } | 
| 210 |  |  |  |  |  |  |  | 
| 211 |  |  |  |  |  |  |  | 
| 212 |  |  |  |  |  |  |  | 
| 213 |  |  |  |  |  |  | # DETECT CENTRED PARAS | 
| 214 |  |  |  |  |  |  |  | 
| 215 | 3 |  |  |  |  | 7 | CHUNK: foreach my $chunk ( @chunks ) | 
| 216 |  |  |  |  |  |  | { | 
| 217 | 13 | 50 | 66 |  |  | 88 | next CHUNK if !$args{autocentre} || @$chunk < 2 || $chunk->[0]{hang}; | 
|  |  |  | 66 |  |  |  |  | 
| 218 | 0 |  |  |  |  | 0 | my @length; | 
| 219 | 0 |  |  |  |  | 0 | my $ave = 0; | 
| 220 | 0 |  |  |  |  | 0 | foreach my $line (@$chunk) | 
| 221 |  |  |  |  |  |  | { | 
| 222 |  |  |  |  |  |  | my $prespace = $line->{quoter}  ? $line->{quotespace} | 
| 223 | 0 | 0 |  |  |  | 0 | : $line->{prespace}; | 
| 224 |  |  |  |  |  |  | my $pagewidth = | 
| 225 | 0 |  |  |  |  | 0 | 2*length($prespace) + length($line->{text}); | 
| 226 | 0 |  |  |  |  | 0 | push @length, [length $prespace,$pagewidth]; | 
| 227 | 0 |  |  |  |  | 0 | $ave += $pagewidth; | 
| 228 |  |  |  |  |  |  | } | 
| 229 | 0 |  |  |  |  | 0 | $ave /= @length; | 
| 230 | 0 |  |  |  |  | 0 | my $diffpre = 0; | 
| 231 | 0 |  |  |  |  | 0 | foreach my $l (0..$#length) | 
| 232 |  |  |  |  |  |  | { | 
| 233 | 0 | 0 |  |  |  | 0 | next CHUNK unless abs($length[$l][1]-$ave) <= 2; | 
| 234 | 0 | 0 | 0 |  |  | 0 | $diffpre ||= $length[$l-1][0] != $length[$l][0] | 
| 235 |  |  |  |  |  |  | if $l > 0; | 
| 236 |  |  |  |  |  |  | } | 
| 237 | 0 | 0 |  |  |  | 0 | next CHUNK unless $diffpre; | 
| 238 | 0 |  |  |  |  | 0 | foreach my $line (@$chunk) | 
| 239 |  |  |  |  |  |  | { | 
| 240 | 0 |  |  |  |  | 0 | $line->{centred} = 1; | 
| 241 |  |  |  |  |  |  | ($line->{quoter} ? $line->{quotespace} | 
| 242 | 0 | 0 |  |  |  | 0 | : $line->{prespace}) = ""; | 
| 243 |  |  |  |  |  |  | } | 
| 244 |  |  |  |  |  |  | } | 
| 245 |  |  |  |  |  |  |  | 
| 246 |  |  |  |  |  |  | # REDIVIDE INTO PARAGRAPHS | 
| 247 |  |  |  |  |  |  |  | 
| 248 | 3 |  |  |  |  | 4 | my @paras; | 
| 249 | 3 |  |  |  |  | 7 | foreach my $chunk ( @chunks ) | 
| 250 |  |  |  |  |  |  | { | 
| 251 | 13 |  |  |  |  | 16 | my $first = 1; | 
| 252 | 13 |  |  |  |  | 13 | my $firstfrom; | 
| 253 | 13 |  |  |  |  | 16 | foreach my $line ( @{$chunk} ) | 
|  | 13 |  |  |  |  | 24 |  | 
| 254 |  |  |  |  |  |  | { | 
| 255 | 26 | 100 | 66 |  |  | 145 | if ($first || | 
|  |  |  | 66 |  |  |  |  | 
|  |  |  | 33 |  |  |  |  | 
| 256 |  |  |  |  |  |  | $line->{quoter} ne $paras[-1]->{quoter} || | 
| 257 |  |  |  |  |  |  | $paras[-1]->{separator} || | 
| 258 |  |  |  |  |  |  | !$line->{hang}->empty | 
| 259 |  |  |  |  |  |  | ) | 
| 260 |  |  |  |  |  |  | { | 
| 261 | 13 |  |  |  |  | 19 | push @paras, $line; | 
| 262 | 13 |  |  |  |  | 15 | $first = 0; | 
| 263 | 13 |  |  |  |  | 28 | $firstfrom = length($line->{raw}) - length($line->{text}); | 
| 264 |  |  |  |  |  |  | } | 
| 265 |  |  |  |  |  |  | else | 
| 266 |  |  |  |  |  |  | { | 
| 267 | 13 |  |  |  |  | 26 | my $extraspace = length($line->{raw}) - length($line->{text}) - $firstfrom; | 
| 268 | 13 |  |  |  |  | 165 | $paras[-1]->{text} .= "\n" . q{ }x$extraspace . $line->{text}; | 
| 269 | 13 |  |  |  |  | 50 | $paras[-1]->{raw} .= "\n" . $line->{raw}; | 
| 270 |  |  |  |  |  |  | } | 
| 271 |  |  |  |  |  |  | } | 
| 272 |  |  |  |  |  |  | } | 
| 273 |  |  |  |  |  |  |  | 
| 274 |  |  |  |  |  |  | # SELECT PARAS TO HANDLE | 
| 275 |  |  |  |  |  |  |  | 
| 276 | 3 |  |  |  |  | 6 | my $remainder = ""; | 
| 277 | 3 | 50 |  |  |  | 10 | if ($args{all}) { # STOP AT MAIL TERMINATOR IF $args{mail} | 
| 278 | 3 |  |  |  |  | 5 | my $lastignored = 1; | 
| 279 | 3 |  |  |  |  | 18 | for my $index (0..$#paras) { | 
| 280 | 13 |  |  |  |  | 64 | local $_ = $paras[$index]{raw} . "\n"; | 
| 281 | 13 |  |  |  |  | 28 | $paras[$index]{ignore} = $args{ignore}($lastignored); | 
| 282 | 13 |  | 100 |  |  | 43 | $lastignored &&= $paras[$index]{ignore}; | 
| 283 | 13 | 50 | 66 |  |  | 70 | next unless $args{mail} && /^--\s*$/; | 
| 284 | 0 |  |  |  |  | 0 | $remainder = join "\n", map { $_->{raw} } splice @paras, $index; | 
|  | 0 |  |  |  |  | 0 |  | 
| 285 | 0 | 0 |  |  |  | 0 | $remainder .= "\n" unless $remainder =~ /\n\z/; | 
| 286 | 0 |  |  |  |  | 0 | last; | 
| 287 |  |  |  |  |  |  | } | 
| 288 |  |  |  |  |  |  | } | 
| 289 |  |  |  |  |  |  | else { # JUST THE FIRST PARA | 
| 290 | 0 |  |  |  |  | 0 | $remainder = join "\n", map { $_->{raw} } @paras[1..$#paras]; | 
|  | 0 |  |  |  |  | 0 |  | 
| 291 | 0 | 0 |  |  |  | 0 | $remainder .= "\n" unless $remainder =~ /\n\z/; | 
| 292 | 0 |  |  |  |  | 0 | @paras = ( $paras[0] ); | 
| 293 |  |  |  |  |  |  | } | 
| 294 |  |  |  |  |  |  |  | 
| 295 |  |  |  |  |  |  | # RE-CASE TEXT | 
| 296 | 3 | 50 |  |  |  | 12 | if ($args{case}) { | 
| 297 | 0 |  |  |  |  | 0 | foreach my $para ( @paras ) { | 
| 298 | 0 | 0 |  |  |  | 0 | next if $para->{ignore}; | 
| 299 | 0 | 0 |  |  |  | 0 | if (ref $args{case} eq 'CODE') { | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
| 300 | 0 |  |  |  |  | 0 | $para->{text} = entitle($para->{text}, $args{case}); | 
| 301 |  |  |  |  |  |  | } | 
| 302 |  |  |  |  |  |  | elsif ($args{case} =~ /upper/i) { | 
| 303 | 0 |  |  |  |  | 0 | $para->{text} = recase($para->{text}, 'upper'); | 
| 304 |  |  |  |  |  |  | } | 
| 305 |  |  |  |  |  |  | elsif ($args{case} =~ /lower/i) { | 
| 306 | 0 |  |  |  |  | 0 | $para->{text} = recase($para->{text}, 'lower'); | 
| 307 |  |  |  |  |  |  | } | 
| 308 |  |  |  |  |  |  | elsif ($args{case} =~ /title/i) { | 
| 309 | 0 |  |  |  |  | 0 | $para->{text} = entitle($para->{text}, 0); | 
| 310 |  |  |  |  |  |  | } | 
| 311 |  |  |  |  |  |  | elsif ($args{case} =~ /highlight/i) { | 
| 312 | 0 |  |  |  |  | 0 | $para->{text} = entitle($para->{text}, $STD_HIGHLIGHT_IGNORES); | 
| 313 |  |  |  |  |  |  | } | 
| 314 |  |  |  |  |  |  | elsif ($args{case} =~ /sentence(\s*)/i) { | 
| 315 | 0 |  |  |  |  | 0 | my $trailer = $1; | 
| 316 | 0 | 0 | 0 |  |  | 0 | $args{squeeze}=0 if $trailer && $trailer ne " "; | 
| 317 | 0 |  |  |  |  | 0 | ensentence(); | 
| 318 | 0 |  |  |  |  | 0 | $para->{text} =~ s/(\S+(\s+|$))/ensentence($1, $trailer)/ge; | 
|  | 0 |  |  |  |  | 0 |  | 
| 319 |  |  |  |  |  |  | } | 
| 320 | 0 |  |  |  |  | 0 | $para->{text} =~ s/\b([A-Z])[.]/\U$1./gi; # ABBREVS | 
| 321 |  |  |  |  |  |  | } | 
| 322 |  |  |  |  |  |  | } | 
| 323 |  |  |  |  |  |  |  | 
| 324 |  |  |  |  |  |  | # ALIGN QUOTERS | 
| 325 |  |  |  |  |  |  | # DETERMINE HANGING MARKER TYPE (BULLET, ALPHA, ROMAN, ETC.) | 
| 326 |  |  |  |  |  |  |  | 
| 327 | 3 |  |  |  |  | 4 | my %sigs; | 
| 328 | 3 |  |  |  |  | 6 | my $lastquoted = 0; | 
| 329 | 3 |  |  |  |  | 5 | my $lastprespace = 0; | 
| 330 | 3 |  |  |  |  | 8 | for my $i ( 0..$#paras ) | 
| 331 |  |  |  |  |  |  | { | 
| 332 | 13 |  |  |  |  | 21 | my $para = $paras[$i]; | 
| 333 | 13 | 100 |  |  |  | 32 | next if $para->{ignore}; | 
| 334 |  |  |  |  |  |  |  | 
| 335 | 9 | 50 |  |  |  | 22 | if ($para->{quoter}) | 
| 336 |  |  |  |  |  |  | { | 
| 337 | 0 | 0 |  |  |  | 0 | if ($lastquoted) { $para->{prespace} = $lastprespace } | 
|  | 0 |  |  |  |  | 0 |  | 
| 338 | 0 |  |  |  |  | 0 | else         { $lastquoted = 1; $lastprespace = $para->{prespace} } | 
|  | 0 |  |  |  |  | 0 |  | 
| 339 |  |  |  |  |  |  | } | 
| 340 |  |  |  |  |  |  | else | 
| 341 |  |  |  |  |  |  | { | 
| 342 | 9 |  |  |  |  | 17 | $lastquoted = 0; | 
| 343 |  |  |  |  |  |  | } | 
| 344 |  |  |  |  |  |  | } | 
| 345 |  |  |  |  |  |  |  | 
| 346 |  |  |  |  |  |  | # RENUMBER PARAGRAPHS | 
| 347 |  |  |  |  |  |  |  | 
| 348 | 3 |  |  |  |  | 8 | for my $para ( @paras ) { | 
| 349 | 13 | 100 |  |  |  | 35 | next if $para->{ignore}; | 
| 350 | 9 |  |  |  |  | 34 | my $sig = $para->{presig} . $para->{hang}->signature(); | 
| 351 | 9 |  |  |  |  | 15 | push @{$sigs{$sig}{hangref}}, $para; | 
|  | 9 |  |  |  |  | 27 |  | 
| 352 |  |  |  |  |  |  | $sigs{$sig}{hangfields} = $para->{hang}->fields()-1 | 
| 353 | 9 | 100 |  |  |  | 40 | unless defined $sigs{$sig}{hangfields}; | 
| 354 |  |  |  |  |  |  | } | 
| 355 |  |  |  |  |  |  |  | 
| 356 | 3 |  |  |  |  | 17 | while (my ($sig,$val) = each %sigs) { | 
| 357 | 3 | 50 |  |  |  | 17 | next unless $sig =~ /rom/; | 
| 358 | 0 |  |  |  |  | 0 | field: for my $field ( 0..$val->{hangfields} ) | 
| 359 |  |  |  |  |  |  | { | 
| 360 | 0 |  |  |  |  | 0 | my $romlen = 0; | 
| 361 | 0 |  |  |  |  | 0 | foreach my $para ( @{$val->{hangref}} ) | 
|  | 0 |  |  |  |  | 0 |  | 
| 362 |  |  |  |  |  |  | { | 
| 363 | 0 |  |  |  |  | 0 | my $hang = $para->{hang}; | 
| 364 | 0 |  |  |  |  | 0 | my $fieldtype = $hang->field($field); | 
| 365 |  |  |  |  |  |  | next field | 
| 366 | 0 | 0 | 0 |  |  | 0 | unless $fieldtype && $fieldtype =~ /rom|let/; | 
| 367 | 0 | 0 |  |  |  | 0 | if ($fieldtype eq 'let') { | 
| 368 | 0 |  |  |  |  | 0 | foreach my $para ( @{$val->{hangref}} ) { | 
|  | 0 |  |  |  |  | 0 |  | 
| 369 | 0 |  |  |  |  | 0 | $hang->field($field=>'let') | 
| 370 |  |  |  |  |  |  | } | 
| 371 |  |  |  |  |  |  | } | 
| 372 |  |  |  |  |  |  | else { | 
| 373 | 0 |  |  |  |  | 0 | $romlen += length $hang->val($field); | 
| 374 |  |  |  |  |  |  | } | 
| 375 |  |  |  |  |  |  | } | 
| 376 |  |  |  |  |  |  | # NO ROMAN LETTER > 1 CHAR -> ALPHABETICS | 
| 377 | 0 | 0 |  |  |  | 0 | if ($romlen <= @{$val->{hangref}}) { | 
|  | 0 |  |  |  |  | 0 |  | 
| 378 | 0 |  |  |  |  | 0 | foreach my $para ( @{$val->{hangref}} ) { | 
|  | 0 |  |  |  |  | 0 |  | 
| 379 | 0 |  |  |  |  | 0 | $para->{hang}->field($field=>'let') | 
| 380 |  |  |  |  |  |  | } | 
| 381 |  |  |  |  |  |  | } | 
| 382 |  |  |  |  |  |  | } | 
| 383 |  |  |  |  |  |  | } | 
| 384 |  |  |  |  |  |  |  | 
| 385 | 3 |  |  |  |  | 5 | my %prev; | 
| 386 |  |  |  |  |  |  |  | 
| 387 | 3 |  |  |  |  | 7 | for my $para ( @paras ) { | 
| 388 | 13 | 100 |  |  |  | 32 | next if $para->{ignore}; | 
| 389 | 9 |  |  |  |  | 25 | my $sig = $para->{presig} . $para->{hang}->signature(); | 
| 390 | 9 | 50 |  |  |  | 24 | if ($args{renumber}) { | 
| 391 | 9 | 50 |  |  |  | 22 | unless ($para->{quoter}) { | 
| 392 | 9 |  |  |  |  | 41 | $para->{hang}->incr($prev{""}, $prev{$sig}); | 
| 393 |  |  |  |  |  |  | $prev{""} = $prev{$sig} = $para->{hang} | 
| 394 | 9 | 50 |  |  |  | 31 | unless $para->{hang}->empty; | 
| 395 |  |  |  |  |  |  | } | 
| 396 |  |  |  |  |  |  | } | 
| 397 |  |  |  |  |  |  |  | 
| 398 |  |  |  |  |  |  | # COLLECT MAXIMAL HANG LENGTHS BY SIGNATURE | 
| 399 |  |  |  |  |  |  |  | 
| 400 | 9 |  |  |  |  | 27 | my $siglen = $para->{hang}->length(); | 
| 401 |  |  |  |  |  |  | $sigs{$sig}{hanglen} = $siglen | 
| 402 |  |  |  |  |  |  | if ! $sigs{$sig}{hanglen} || | 
| 403 | 9 | 50 | 33 |  |  | 46 | $sigs{$sig}{hanglen} < $siglen; | 
| 404 |  |  |  |  |  |  | } | 
| 405 |  |  |  |  |  |  |  | 
| 406 |  |  |  |  |  |  | # PROPAGATE MAXIMAL HANG LENGTH | 
| 407 |  |  |  |  |  |  |  | 
| 408 | 3 |  |  |  |  | 13 | while (my ($sig,$val) = each %sigs) | 
| 409 |  |  |  |  |  |  | { | 
| 410 | 3 |  |  |  |  | 8 | foreach (@{$val->{hangref}}) { | 
|  | 3 |  |  |  |  | 10 |  | 
| 411 | 9 |  |  |  |  | 25 | $_->{hanglen} = $val->{hanglen}; | 
| 412 |  |  |  |  |  |  | } | 
| 413 |  |  |  |  |  |  | } | 
| 414 |  |  |  |  |  |  |  | 
| 415 |  |  |  |  |  |  | # BUILD FORMAT FOR EACH PARA THEN FILL IT | 
| 416 |  |  |  |  |  |  |  | 
| 417 | 3 |  |  |  |  | 5 | $text = ""; | 
| 418 | 3 | 50 | 33 |  |  | 16 | my $gap = @paras && $paras[0]->{empty} ? 0 : $args{gap}; | 
| 419 | 3 |  |  |  |  | 8 | for my $para ( @paras ) | 
| 420 |  |  |  |  |  |  | { | 
| 421 | 13 | 100 |  |  |  | 29 | if ($para->{empty}) { | 
| 422 | 5 |  |  |  |  | 11 | $gap += 1 + ($para->{text} =~ tr/\n/\n/); | 
| 423 |  |  |  |  |  |  | } | 
| 424 | 13 | 100 |  |  |  | 24 | if ($para->{ignore}) { | 
| 425 | 4 | 50 |  |  |  | 142 | $text .= (!$para->{empty} ? "\n"x($args{gap}-$gap) : "") ; | 
| 426 | 4 |  |  |  |  | 13 | $text .= $para->{raw}; | 
| 427 | 4 | 50 |  |  |  | 13 | $text .= "\n" unless $para->{raw} =~ /\n\z/; | 
| 428 |  |  |  |  |  |  | } | 
| 429 |  |  |  |  |  |  | else { | 
| 430 |  |  |  |  |  |  | my $leftmargin = $args{left} ? " "x($args{left}-1) | 
| 431 | 9 | 50 |  |  |  | 24 | : $para->{prespace}; | 
| 432 | 9 |  | 33 |  |  | 43 | my $hlen = $para->{hanglen} || $para->{hang}->length; | 
| 433 | 9 | 50 |  |  |  | 26 | my $hfield = ($hlen==1 ? '~' : '>'x$hlen); | 
| 434 | 9 |  |  |  |  | 11 | my @hang; | 
| 435 | 9 | 50 |  |  |  | 19 | push @hang, $para->{hang}->stringify if $hlen; | 
| 436 |  |  |  |  |  |  | my $format = $leftmargin | 
| 437 |  |  |  |  |  |  | . quotemeta($para->{quoter}) | 
| 438 |  |  |  |  |  |  | . $para->{quotespace} | 
| 439 |  |  |  |  |  |  | . $hfield | 
| 440 | 9 |  |  |  |  | 29 | . $para->{hangspace}; | 
| 441 | 9 |  |  |  |  | 27 | my $rightslack = int (($args{right}-length $leftmargin)*$Text::Autoformat::widow_slack); | 
| 442 | 9 |  |  |  |  | 13 | my ($widow_okay, $rightindent, $firsttext, $newtext) = (0,0); | 
| 443 | 9 |  | 33 |  |  | 11 | do { | 
| 444 |  |  |  |  |  |  | my $tlen = $args{right}-$rightindent-length($leftmargin | 
| 445 |  |  |  |  |  |  | . $para->{quoter} | 
| 446 |  |  |  |  |  |  | . $para->{quotespace} | 
| 447 |  |  |  |  |  |  | . $hfield | 
| 448 | 9 |  |  |  |  | 24 | . $para->{hangspace}); | 
| 449 | 9 | 50 |  |  |  | 34 | next if blockquote($text,$para, $format, $tlen, \@hang, \%args); | 
| 450 |  |  |  |  |  |  | my $tfield = ( $tlen==1                          ? '~' | 
| 451 |  |  |  |  |  |  | : $para->{centred}||$args{_centred} ? '|'x$tlen | 
| 452 |  |  |  |  |  |  | : $args{justify} eq 'right'         ? ']'x$tlen | 
| 453 |  |  |  |  |  |  | : $args{justify} eq 'full'          ? '['x($tlen-2) . ']]' | 
| 454 | 9 | 50 | 33 |  |  | 89 | : $para->{centred}||$args{_centred} ? '|'x$tlen | 
|  |  | 50 | 33 |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
| 455 |  |  |  |  |  |  | :                                     '['x$tlen | 
| 456 |  |  |  |  |  |  | ); | 
| 457 | 9 |  |  |  |  | 15 | my $tryformat = "$format$tfield"; | 
| 458 |  |  |  |  |  |  | $newtext = (!$para->{empty} ? "\n"x($args{gap}-$gap) : "") | 
| 459 |  |  |  |  |  |  | . form( { squeeze=>$args{squeeze}, trim=>1, | 
| 460 |  |  |  |  |  |  | break=>$args{break}, | 
| 461 |  |  |  |  |  |  | fill => !(!($args{expfill} | 
| 462 |  |  |  |  |  |  | || $args{impfill} && | 
| 463 |  |  |  |  |  |  | !$para->{centred})) | 
| 464 |  |  |  |  |  |  | }, | 
| 465 |  |  |  |  |  |  | $tryformat, @hang, | 
| 466 | 9 | 100 | 33 |  |  | 245 | $para->{text}); | 
| 467 | 9 |  | 33 |  |  | 5234 | $firsttext ||= $newtext; | 
| 468 | 9 |  |  |  |  | 61 | (my $widow) = $newtext =~ /([^\n]*)$/; | 
| 469 | 9 |  |  |  |  | 20 | $widow =~ s/^\s+//; | 
| 470 | 9 |  | 66 |  |  | 68 | $widow_okay = $para->{empty} || length($widow) >= $args{widow}; | 
| 471 |  |  |  |  |  |  | } until $widow_okay || ++$rightindent > $rightslack; | 
| 472 |  |  |  |  |  |  |  | 
| 473 | 9 | 50 |  |  |  | 34 | $text .= $widow_okay ? $newtext : $firsttext; | 
| 474 |  |  |  |  |  |  | } | 
| 475 | 13 | 100 |  |  |  | 39 | $gap = 0 unless $para->{empty}; | 
| 476 |  |  |  |  |  |  | } | 
| 477 |  |  |  |  |  |  |  | 
| 478 |  |  |  |  |  |  |  | 
| 479 |  |  |  |  |  |  | # RETURN FORMATTED TEXT | 
| 480 |  |  |  |  |  |  |  | 
| 481 | 3 | 50 |  |  |  | 11 | if ($toSTDOUT) { print STDOUT $text . $remainder; return } | 
|  | 0 |  |  |  |  | 0 |  | 
|  | 0 |  |  |  |  | 0 |  | 
| 482 | 3 |  |  |  |  | 107 | return $text . $remainder; | 
| 483 |  |  |  |  |  |  | } | 
| 484 |  |  |  |  |  |  |  | 
| 485 |  |  |  |  |  |  | sub _build_ignore { | 
| 486 | 4 |  |  | 4 |  | 8 | my $ignore_arg = shift; | 
| 487 | 4 |  |  |  |  | 8 | my $ig_type = ref $ignore_arg; | 
| 488 | 4 |  |  |  |  | 5 | my $ignore; | 
| 489 | 4 | 100 |  |  |  | 10 | if ($ig_type eq 'Regexp') { | 
|  |  | 50 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
| 490 | 3 |  |  |  |  | 5 | my $regex = $ignore_arg; | 
| 491 | 3 |  |  | 16 |  | 12 | $ignore = sub { /$regex/ }; | 
|  | 16 |  |  |  |  | 89 |  | 
| 492 |  |  |  |  |  |  | } elsif ($ig_type eq 'ARRAY') { | 
| 493 | 1 |  |  |  |  | 3 | my @elements = map { _build_ignore($_) } @$ignore_arg; | 
|  | 2 |  |  |  |  | 7 |  | 
| 494 |  |  |  |  |  |  | $ignore = sub { | 
| 495 | 5 | 100 |  | 5 |  | 7 | for my $sub (@elements) { return 1 if $sub->(@_) } | 
|  | 9 |  |  |  |  | 17 |  | 
| 496 | 3 |  |  |  |  | 7 | return 0; | 
| 497 | 1 |  |  |  |  | 7 | }; | 
| 498 |  |  |  |  |  |  | } | 
| 499 |  |  |  |  |  |  | elsif ($ignore_arg =~ /^indent/i) { | 
| 500 | 0 | 0 |  | 0 |  | 0 | $ignore = sub { ignore_headers(@_) || /$ignore_indent/ }; | 
|  | 0 |  |  |  |  | 0 |  | 
| 501 |  |  |  |  |  |  | } | 
| 502 |  |  |  |  |  |  | else { | 
| 503 | 0 |  |  |  |  | 0 | $ignore = $ignore_arg; | 
| 504 |  |  |  |  |  |  | } | 
| 505 | 4 | 50 |  |  |  | 13 | croak "Expected suboutine reference as value for -ignore option" | 
| 506 |  |  |  |  |  |  | if ref $ignore ne 'CODE'; | 
| 507 | 4 |  |  |  |  | 12 | return $ignore; | 
| 508 |  |  |  |  |  |  | } | 
| 509 |  |  |  |  |  |  |  | 
| 510 |  |  |  |  |  |  | my $alpha = qr/[^\W\d_]/; | 
| 511 |  |  |  |  |  |  | my $notalpha = qr/[\W\d_]/; | 
| 512 | 4 |  |  | 4 |  | 4696 | my $word = qr/\pL(?:\pL'?)*/; | 
|  | 4 |  |  |  |  | 36 |  | 
|  | 4 |  |  |  |  | 58 |  | 
| 513 |  |  |  |  |  |  | my $upper = qr/[^\Wa-z\d_]/; | 
| 514 |  |  |  |  |  |  | my $lower = qr/[^\WA-Z\d_]/; | 
| 515 |  |  |  |  |  |  | my $mixed = qr/$alpha*?(?:$lower$upper|$upper$lower)$alpha*/; | 
| 516 |  |  |  |  |  |  |  | 
| 517 |  |  |  |  |  |  | sub recase { | 
| 518 | 0 |  |  | 0 | 0 | 0 | my ($origtext, $case) = @_; | 
| 519 | 0 |  |  |  |  | 0 | my ($entities, $other_entities, $first, $rest) = @{$casing{$case}}; | 
|  | 0 |  |  |  |  | 0 |  | 
| 520 |  |  |  |  |  |  |  | 
| 521 | 0 |  |  |  |  | 0 | my $text = ""; | 
| 522 | 0 |  |  |  |  | 0 | my @pieces = split /(&[a-z]+;)/i, $origtext; | 
| 523 | 0 | 0 |  |  |  | 0 | push @pieces, "" if @pieces % 2; | 
| 524 | 0 | 0 |  |  |  | 0 | return $text unless @pieces; | 
| 525 | 0 |  |  |  |  | 0 | local $_ = shift @pieces; | 
| 526 | 0 | 0 |  |  |  | 0 | if (length $_) { | 
| 527 | 0 |  |  |  |  | 0 | $entities = $other_entities; | 
| 528 | 0 |  |  |  |  | 0 | &$first; | 
| 529 | 0 |  |  |  |  | 0 | $text .= $_; | 
| 530 |  |  |  |  |  |  | } | 
| 531 | 0 | 0 |  |  |  | 0 | return $text unless @pieces; | 
| 532 | 0 |  |  |  |  | 0 | $_ = shift @pieces; | 
| 533 | 0 |  | 0 |  |  | 0 | $text .= $entities->{$_} || $_; | 
| 534 | 0 |  |  |  |  | 0 | while (@pieces) { | 
| 535 | 0 |  |  |  |  | 0 | $_ = shift @pieces; &$rest; $text .= $_; | 
|  | 0 |  |  |  |  | 0 |  | 
|  | 0 |  |  |  |  | 0 |  | 
| 536 | 0 |  | 0 |  |  | 0 | $_ = shift @pieces; $text .= $other_entities->{$_} || $_; | 
|  | 0 |  |  |  |  | 0 |  | 
| 537 |  |  |  |  |  |  | } | 
| 538 | 0 |  |  |  |  | 0 | return $text; | 
| 539 |  |  |  |  |  |  | } | 
| 540 |  |  |  |  |  |  |  | 
| 541 |  |  |  |  |  |  | my $alword = qr{(?:\pL|&[a-z]+;)(?:[\pL']|&[a-z]+;)*}i; | 
| 542 |  |  |  |  |  |  |  | 
| 543 |  |  |  |  |  |  | sub entitle { | 
| 544 | 0 |  |  | 0 | 0 | 0 | my ($text, $retitler_ref) = @_; | 
| 545 |  |  |  |  |  |  |  | 
| 546 |  |  |  |  |  |  | # put into lowercase if on stop list, else titlecase | 
| 547 | 0 |  |  |  |  | 0 | $text =~ s{($alword)} | 
| 548 | 0 | 0 |  |  |  | 0 | { $retitler_ref ? $retitler_ref->($1) : recase($1,'title') }gex; | 
| 549 |  |  |  |  |  |  |  | 
| 550 | 0 | 0 |  |  |  | 0 | if ($retitler_ref == $STD_HIGHLIGHT_IGNORES) { | 
| 551 |  |  |  |  |  |  | # First and final words always capitalized... | 
| 552 | 0 |  |  |  |  | 0 | $text =~ s/^($alword) /recase($1,'title')/ex; | 
|  | 0 |  |  |  |  | 0 |  | 
| 553 | 0 |  |  |  |  | 0 | $text =~ s/ ($alword)$/recase($1,'title')/ex; | 
|  | 0 |  |  |  |  | 0 |  | 
| 554 |  |  |  |  |  |  |  | 
| 555 |  |  |  |  |  |  | # treat parethesized portion as a complete title | 
| 556 | 0 |  |  |  |  | 0 | $text =~ s/\( ($alword) /'('.recase($1,'title')/ex; | 
|  | 0 |  |  |  |  | 0 |  | 
| 557 | 0 |  |  |  |  | 0 | $text =~ s/($alword) \) /recase($1,'title').')'/ex; | 
|  | 0 |  |  |  |  | 0 |  | 
| 558 |  |  |  |  |  |  |  | 
| 559 |  |  |  |  |  |  | # capitalize first word following colon or semi-colon | 
| 560 | 0 |  |  |  |  | 0 | $text =~ s/ ( [:;] \s+ ) ($alword) /$1 . recase($2,'title')/ex; | 
|  | 0 |  |  |  |  | 0 |  | 
| 561 |  |  |  |  |  |  | } | 
| 562 |  |  |  |  |  |  |  | 
| 563 | 0 |  |  |  |  | 0 | return $text; | 
| 564 |  |  |  |  |  |  | } | 
| 565 |  |  |  |  |  |  |  | 
| 566 |  |  |  |  |  |  | my $gen_abbrev = join '|', | 
| 567 |  |  |  |  |  |  | qw{ etc[.]  pp[.]   ph[.]?d[.] }, | 
| 568 |  |  |  |  |  |  | '(?:[A-Z][.])(?:[A-Z][.])+', | 
| 569 |  |  |  |  |  |  | '(^[^a-zA-Z]*([a-z][.])+)'; | 
| 570 |  |  |  |  |  |  |  | 
| 571 |  |  |  |  |  |  | my $term = q{(?:[.]|[!?]+)}; | 
| 572 |  |  |  |  |  |  |  | 
| 573 |  |  |  |  |  |  | my $eos = 1; | 
| 574 |  |  |  |  |  |  | my $brsent = 0; | 
| 575 |  |  |  |  |  |  |  | 
| 576 |  |  |  |  |  |  | sub ensentence { | 
| 577 | 0 | 0 |  | 0 | 0 | 0 | do { $eos = 1; return } unless @_; | 
|  | 0 |  |  |  |  | 0 |  | 
|  | 0 |  |  |  |  | 0 |  | 
| 578 | 0 |  |  |  |  | 0 | my ($str, $trailer) = @_; | 
| 579 | 0 | 0 |  |  |  | 0 | if ($str =~ /^([^a-z]*)I[^a-z]*?($term?)[^a-z]*$/i) { | 
| 580 | 0 |  |  |  |  | 0 | $eos = $2; | 
| 581 | 0 |  |  |  |  | 0 | $brsent = $1 =~ /^[[(]/; | 
| 582 | 0 |  |  |  |  | 0 | return uc $str | 
| 583 |  |  |  |  |  |  | } | 
| 584 | 0 | 0 |  |  |  | 0 | unless ($str =~ /[a-z].*[A-Z]|[A-Z].*[a-z]/) { | 
| 585 | 0 |  |  |  |  | 0 | $str = lc $str; | 
| 586 |  |  |  |  |  |  | } | 
| 587 | 0 | 0 |  |  |  | 0 | if ($eos) { | 
| 588 | 0 |  |  |  |  | 0 | $str =~ s/([a-z])/uc $1/ie; | 
|  | 0 |  |  |  |  | 0 |  | 
| 589 | 0 |  |  |  |  | 0 | $brsent = $str =~ /^[[(]/; | 
| 590 |  |  |  |  |  |  | } | 
| 591 | 0 |  | 0 |  |  | 0 | $eos = $str !~ /^($gen_abbrev)[^a-z]*\s/i | 
| 592 |  |  |  |  |  |  | && $str =~ /[a-z][^a-z]*$term([^a-z]*)\s/ | 
| 593 |  |  |  |  |  |  | && !($1=~/[])]/ && !$brsent); | 
| 594 | 0 | 0 | 0 |  |  | 0 | $str =~ s/\s+$/$trailer/ if $eos && $trailer; | 
| 595 | 0 |  |  |  |  | 0 | return $str; | 
| 596 |  |  |  |  |  |  | } | 
| 597 |  |  |  |  |  |  |  | 
| 598 |  |  |  |  |  |  | # blockquote($text,$para, $format, $tlen, \@hang, \%args); | 
| 599 |  |  |  |  |  |  | sub blockquote { | 
| 600 | 9 |  |  | 9 | 0 | 15 | my ($dummy, $para, $format, $tlen, $hang, $args) = @_; | 
| 601 |  |  |  |  |  |  |  | 
| 602 |  |  |  |  |  |  | $para->{text} =~ | 
| 603 | 9 | 50 |  |  |  | 45 | / \A(\s*)       # $1 - leading whitespace (quotation) | 
| 604 |  |  |  |  |  |  | (["']|``)        # $2 - opening quotemark | 
| 605 |  |  |  |  |  |  | (.*)         # $3 - quotation | 
| 606 |  |  |  |  |  |  | (''|\2)      # $4 closing quotemark | 
| 607 |  |  |  |  |  |  | \s*?\n       # trailing whitespace | 
| 608 |  |  |  |  |  |  | (\1[ ]+)     # $5 - leading whitespace (attribution) | 
| 609 |  |  |  |  |  |  | (--|-)       # $6 - attribution introducer | 
| 610 |  |  |  |  |  |  | (.*?$)       # $7 - attribution line 1 | 
| 611 |  |  |  |  |  |  | ((\5.*?$)*)      # $8 - attributions lines 2-N | 
| 612 |  |  |  |  |  |  | \s*\Z | 
| 613 |  |  |  |  |  |  | /xsm | 
| 614 |  |  |  |  |  |  | or return; | 
| 615 |  |  |  |  |  |  |  | 
| 616 |  |  |  |  |  |  | #print "[$1][$2][$3][$4][$5][$6][$7]\n"; | 
| 617 | 0 |  |  |  |  |  | my $indent = length $1; | 
| 618 | 0 |  |  |  |  |  | my $text = $2.$3.$4; | 
| 619 | 0 |  |  |  |  |  | my $qindent = length $2; | 
| 620 | 0 |  |  |  |  |  | my $aindent = length $5; | 
| 621 | 0 |  |  |  |  |  | my $attribintro = $6; | 
| 622 | 0 |  |  |  |  |  | my $attrib = $7.$8; | 
| 623 | 0 |  |  |  |  |  | $text =~ s/\n/ /g; | 
| 624 |  |  |  |  |  |  |  | 
| 625 |  |  |  |  |  |  | $_[0] .= | 
| 626 |  |  |  |  |  |  |  | 
| 627 |  |  |  |  |  |  | form {squeeze=>$args->{squeeze}, trim=>1, | 
| 628 |  |  |  |  |  |  | fill => $args->{expfill} | 
| 629 |  |  |  |  |  |  | }, | 
| 630 | 0 |  |  |  |  |  | $format . q{ }x$indent . q{<}x$tlen, | 
| 631 |  |  |  |  |  |  | @$hang, $text, | 
| 632 |  |  |  |  |  |  | $format . q{ }x($qindent) . q{[}x($tlen-$qindent), | 
| 633 |  |  |  |  |  |  | @$hang, $text, | 
| 634 |  |  |  |  |  |  | {squeeze=>0}, | 
| 635 |  |  |  |  |  |  | $format . q{ } x $aindent . q{>> } . q{[}x($tlen-$aindent-3), | 
| 636 |  |  |  |  |  |  | @$hang, $attribintro, $attrib; | 
| 637 | 0 |  |  |  |  |  | return 1; | 
| 638 |  |  |  |  |  |  | } | 
| 639 |  |  |  |  |  |  |  | 
| 640 |  |  |  |  |  |  | 1; | 
| 641 |  |  |  |  |  |  |  | 
| 642 |  |  |  |  |  |  | __END__ |