File Coverage

blib/lib/Text/WrapProp.pm
Criterion Covered Total %
statement 33 33 100.0
branch 9 10 90.0
condition 3 3 100.0
subroutine 3 3 100.0
pod 0 1 0.0
total 48 50 96.0


line stmt bran cond sub pod time code
1             package Text::WrapProp;
2              
3 1     1   1896 use strict;
  1         3  
  1         61  
4 1     1   6 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);
  1         1  
  1         606  
5              
6             require Exporter;
7              
8             @ISA = qw(Exporter AutoLoader);
9             # Items to export into callers namespace by default. Note: do not export
10             # names by default without a very good reason. Use EXPORT_OK instead.
11             # Do not simply export all your public functions/methods/constants.
12             @EXPORT = qw( wrap_prop
13            
14             );
15              
16             $VERSION = '0.01';
17              
18             # Preloaded methods go here.
19              
20             # Autoload methods go after =cut, and are processed by the autosplit program.
21              
22             1;
23              
24             sub wrap_prop {
25 1     1 0 113 my ($text, $width, $ref_width_table) = @_;
26              
27 1         486 my @width_table = @$ref_width_table;
28              
29 1 50       7 return '' if $text eq '';
30              
31             # simplify whitespace, including newlines
32 1         27 $text =~ s/\s+/ /gs;
33              
34 1         3 my $cursor = 0; # width so far of line
35 1         2 my $c; # current character
36             my $out; # output buffer
37 1         3 my $nextline = '';
38              
39 1         2 my $i=0;
40              
41 1         3 my $ltext = length $text;
42              
43             # tried regex scanning, but 50% slower than C-style char processing!
44             # like this... while ($text =~ /(.)/gcs) {
45            
46 1         5 while ($i < $ltext) {
47             # pop off next character
48 314         419 $c = substr($text,$i++,1);
49            
50             # don't need leading spaces at start of line
51 314 100 100     1818 next if $nextline eq '' and $c eq ' ';
52              
53             # see if character will fit on line - but don't include if too long
54 312 100       961 if ($cursor + $width_table[ord $c] <= $width) {
55             # another character fits
56 297         316 $nextline .= $c;
57 297         1198 $cursor += $width_table[ord $c];
58             }
59             else {
60             # find where we can wrap by checking backwards for separator
61 15         20 my $j = length($nextline);
62 15         101 foreach (split '', reverse $nextline) { # find separator
63 123         612 $j--;
64 123 100       601 last if /( |:|;|,|\.|-|\(|\)|\/)/o; # separator characters
65             }
66              
67             # see if no separator found
68 15 100       55 if (!$j) { # no separator, so just truncate line right here
69 3         5 $i--; # rerun on $c
70 3         10 $out .= $nextline."\n";
71             }
72             #
73             else { # separator found, so break line at separator
74 12         17 $i -= length($nextline) - $j; # rerun characters after separator
75 12         33 $out .= substr($nextline, 0, $j+1)."\n";
76             }
77              
78 15         22 $nextline = '';
79 15         37 $cursor = 0;
80             }
81             }
82              
83 1         26 $out.$nextline;
84             }
85              
86             __END__