line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Text::Reform;
|
2
|
|
|
|
|
|
|
|
3
|
2
|
|
|
2
|
|
68280
|
use strict; use vars qw($VERSION @ISA @EXPORT @EXPORT_OK); use Carp;
|
|
2
|
|
|
2
|
|
5
|
|
|
2
|
|
|
2
|
|
83
|
|
|
2
|
|
|
|
|
10
|
|
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
162
|
|
|
2
|
|
|
|
|
13
|
|
|
2
|
|
|
|
|
7
|
|
|
2
|
|
|
|
|
189
|
|
4
|
2
|
|
|
2
|
|
47
|
use 5.005;
|
|
2
|
|
|
|
|
6
|
|
|
2
|
|
|
|
|
831
|
|
5
|
|
|
|
|
|
|
#use version;
|
6
|
|
|
|
|
|
|
$VERSION = '1.20';
|
7
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
require Exporter;
|
9
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
@ISA = qw(Exporter);
|
11
|
|
|
|
|
|
|
@EXPORT = qw( form );
|
12
|
|
|
|
|
|
|
@EXPORT_OK = qw( columns tag break_with break_at break_wrap break_TeX debug );
|
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
my @bspecials = qw( [ | ] );
|
15
|
|
|
|
|
|
|
my @lspecials = qw( < ^ > );
|
16
|
|
|
|
|
|
|
my $ljustified = '[<]{2,}[>]{2,}';
|
17
|
|
|
|
|
|
|
my $bjustified = '[[]{2,}[]]{2,}';
|
18
|
|
|
|
|
|
|
my $bsingle = '~+';
|
19
|
|
|
|
|
|
|
my @specials = (@bspecials, @lspecials);
|
20
|
|
|
|
|
|
|
my $fixed_fieldpat = join('|', ($ljustified, $bjustified,
|
21
|
|
|
|
|
|
|
$bsingle,
|
22
|
|
|
|
|
|
|
map { "\\$_\{2,}" } @specials));
|
23
|
|
|
|
|
|
|
my ($lfieldmark, $bfieldmark, $fieldmark, $fieldpat, $decimal);
|
24
|
|
|
|
|
|
|
my $emptyref = '';
|
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
sub import
|
27
|
|
|
|
|
|
|
{
|
28
|
|
|
|
|
|
|
#$decimal = localeconv()->{decimal_point} || '.';
|
29
|
2
|
|
|
2
|
|
26
|
$decimal = '.';
|
30
|
|
|
|
|
|
|
|
31
|
2
|
|
|
|
|
7
|
my $lnumerical = '[>]+(?:'.quotemeta($decimal).'[<]{1,})';
|
32
|
2
|
|
|
|
|
8
|
my $bnumerical = '[]]+(?:'.quotemeta($decimal).'[[]{1,})';
|
33
|
|
|
|
|
|
|
|
34
|
2
|
|
|
|
|
7
|
$fieldpat = join('|', ($lnumerical, $bnumerical,$fixed_fieldpat));
|
35
|
|
|
|
|
|
|
|
36
|
2
|
|
|
|
|
6
|
$lfieldmark = join '|', ($lnumerical, $ljustified, map { "\\$_\{2}" } @lspecials);
|
|
6
|
|
|
|
|
18
|
|
37
|
2
|
|
|
|
|
7
|
$bfieldmark = join '|', ($bnumerical, $bjustified, $bsingle, map { "\\$_\{2}" } @bspecials);
|
|
6
|
|
|
|
|
15
|
|
38
|
2
|
|
|
|
|
9
|
$fieldmark = join '|', ($lnumerical, $bnumerical,
|
39
|
|
|
|
|
|
|
$bsingle,
|
40
|
|
|
|
|
|
|
$ljustified, $bjustified,
|
41
|
|
|
|
|
|
|
$lfieldmark, $bfieldmark);
|
42
|
|
|
|
|
|
|
|
43
|
2
|
|
|
|
|
289
|
Text::Reform->export_to_level(1, @_);
|
44
|
|
|
|
|
|
|
}
|
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
sub carpfirst {
|
47
|
2
|
|
|
2
|
|
12
|
use vars '%carped';
|
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
7848
|
|
48
|
0
|
|
|
0
|
0
|
0
|
my ($msg) = @_;
|
49
|
0
|
0
|
|
|
|
0
|
return if $carped{$msg}++;
|
50
|
0
|
|
|
|
|
0
|
carp $msg;
|
51
|
|
|
|
|
|
|
}
|
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
###### USEFUL TOOLS ######################################
|
54
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
#===== form =============================================#
|
56
|
|
|
|
|
|
|
|
57
|
1
|
|
|
1
|
0
|
227
|
sub BAD_CONFIG { 'Configuration hash not allowed between format and data' }
|
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
sub break_with
|
60
|
|
|
|
|
|
|
{
|
61
|
10
|
|
|
10
|
0
|
3881
|
my $hyphen = $_[0];
|
62
|
10
|
|
|
|
|
19
|
my $hylen = length($hyphen);
|
63
|
10
|
|
|
|
|
12
|
my @ret;
|
64
|
|
|
|
|
|
|
sub
|
65
|
|
|
|
|
|
|
{
|
66
|
42
|
50
|
|
42
|
|
71
|
if ($_[2]<=$hylen)
|
67
|
|
|
|
|
|
|
{
|
68
|
0
|
|
|
|
|
0
|
@ret = (substr($_[0],0,1), substr($_[0],1))
|
69
|
|
|
|
|
|
|
}
|
70
|
|
|
|
|
|
|
else
|
71
|
|
|
|
|
|
|
{
|
72
|
42
|
|
|
|
|
158
|
@ret = (substr($_[0],0,$_[1]-$hylen),
|
73
|
|
|
|
|
|
|
substr($_[0],$_[1]-$hylen))
|
74
|
|
|
|
|
|
|
}
|
75
|
42
|
50
|
|
|
|
133
|
if ($ret[0] =~ /\A\s*\Z/) { return ("",$_[0]); }
|
|
0
|
|
|
|
|
0
|
|
76
|
42
|
|
|
|
|
121
|
else { return ($ret[0].$hyphen,$ret[1]); }
|
77
|
|
|
|
|
|
|
}
|
78
|
|
|
|
|
|
|
|
79
|
10
|
|
|
|
|
104
|
}
|
80
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
sub break_at {
|
82
|
4
|
|
|
4
|
0
|
1026
|
my ($hyphen, $opts_ref) = @_;
|
83
|
4
|
|
|
|
|
7
|
my $hylen = length($hyphen);
|
84
|
4
|
|
|
|
|
8
|
my $except = $opts_ref->{except};
|
85
|
4
|
|
|
|
|
6
|
my @ret;
|
86
|
|
|
|
|
|
|
sub
|
87
|
|
|
|
|
|
|
{
|
88
|
10
|
|
|
10
|
|
14
|
my $max = $_[2]-$hylen;
|
89
|
10
|
50
|
100
|
|
|
180
|
if ($max <= 0) {
|
|
|
100
|
66
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
90
|
0
|
|
|
|
|
0
|
@ret = (substr($_[0],0,1), substr($_[0],1))
|
91
|
|
|
|
|
|
|
}
|
92
|
|
|
|
|
|
|
elsif (defined $except && $_[0] =~ m/\A (.{1,$max}) ($except .*)/xms) {
|
93
|
1
|
|
|
|
|
4
|
@ret = ($1,$2);
|
94
|
|
|
|
|
|
|
}
|
95
|
|
|
|
|
|
|
elsif (defined $except && $_[0] =~ m/\A ($except) (.*)/xms) {
|
96
|
1
|
|
|
|
|
3
|
@ret = ($1,$2);
|
97
|
|
|
|
|
|
|
}
|
98
|
|
|
|
|
|
|
elsif ($_[0] =~ /\A (.{1,$max}$hyphen) (.*)/xms) {
|
99
|
0
|
|
|
|
|
0
|
@ret = ($1,$2);
|
100
|
|
|
|
|
|
|
}
|
101
|
|
|
|
|
|
|
elsif (length($_[0])>$_[2]) {
|
102
|
8
|
|
|
|
|
37
|
@ret = (substr($_[0],0,$_[1]-$hylen).$hyphen,
|
103
|
|
|
|
|
|
|
substr($_[0],$_[1]-$hylen))
|
104
|
|
|
|
|
|
|
}
|
105
|
|
|
|
|
|
|
else {
|
106
|
0
|
|
|
|
|
0
|
@ret = ("",$_[0]);
|
107
|
|
|
|
|
|
|
}
|
108
|
10
|
50
|
|
|
|
33
|
if ($ret[0] =~ /\A\s*\Z/) { return ("",$_[0]); }
|
|
0
|
|
|
|
|
0
|
|
109
|
10
|
|
|
|
|
28
|
else { return @ret; }
|
110
|
|
|
|
|
|
|
}
|
111
|
4
|
|
|
|
|
46
|
}
|
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
sub break_wrap
|
114
|
|
|
|
|
|
|
{
|
115
|
5
|
100
|
|
5
|
0
|
851
|
return \&break_wrap unless @_;
|
116
|
3
|
|
|
|
|
6
|
my ($text, $reqlen, $fldlen) = @_;
|
117
|
3
|
100
|
|
|
|
8
|
if ($reqlen==$fldlen) { $text =~ m/\A(\s*\S*)(.*)/s }
|
|
2
|
|
|
|
|
10
|
|
118
|
1
|
|
|
|
|
4
|
else { ("", $text) }
|
119
|
|
|
|
|
|
|
}
|
120
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
my %hyp;
|
122
|
|
|
|
|
|
|
sub break_TeX
|
123
|
|
|
|
|
|
|
{
|
124
|
0
|
|
0
|
0
|
0
|
0
|
my $file = $_[0] || "";
|
125
|
|
|
|
|
|
|
|
126
|
0
|
0
|
|
|
|
0
|
croak "Can't find TeX::Hyphen module"
|
127
|
|
|
|
|
|
|
unless require "TeX/Hyphen.pm";
|
128
|
|
|
|
|
|
|
|
129
|
0
|
0
|
0
|
|
|
0
|
$hyp{$file} = TeX::Hyphen->new($file||undef)
|
130
|
|
|
|
|
|
|
|| croak "Can't open hyphenation file $file"
|
131
|
|
|
|
|
|
|
unless $hyp{$file};
|
132
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
return sub {
|
134
|
0
|
|
|
0
|
|
0
|
for (reverse $hyp{$file}->hyphenate($_[0])) {
|
135
|
0
|
0
|
|
|
|
0
|
if ($_ < $_[1]) {
|
136
|
0
|
|
|
|
|
0
|
return (substr($_[0],0,$_).'-',
|
137
|
|
|
|
|
|
|
substr($_[0],$_) );
|
138
|
|
|
|
|
|
|
}
|
139
|
|
|
|
|
|
|
}
|
140
|
0
|
|
|
|
|
0
|
return ("",$_[0]);
|
141
|
|
|
|
|
|
|
}
|
142
|
0
|
|
|
|
|
0
|
}
|
143
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
my $debug = 0;
|
145
|
2880
|
50
|
|
2880
|
|
6765
|
sub _debug { print STDERR @_, "\n" if $debug }
|
146
|
0
|
|
|
0
|
0
|
0
|
sub debug { $debug = 1; }
|
147
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
sub notempty
|
149
|
|
|
|
|
|
|
{
|
150
|
142
|
|
|
142
|
0
|
135
|
my $ne = ${$_[0]} =~ /\S/;
|
|
142
|
|
|
|
|
333
|
|
151
|
142
|
|
|
|
|
160
|
_debug("\tnotempty('${$_[0]}') = $ne\n");
|
|
142
|
|
|
|
|
423
|
|
152
|
142
|
|
|
|
|
607
|
return $ne;
|
153
|
|
|
|
|
|
|
}
|
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
sub strtod1 {
|
156
|
27
|
|
|
27
|
0
|
40
|
my $n=shift;
|
157
|
27
|
|
|
|
|
45
|
my $real_re='((?:[+-]?)(?:(?=[0123456789]|[.])(?:[0123456789]*)(?:(?:[.])(?:[0123456789]{0,}))?)'.
|
158
|
|
|
|
|
|
|
'(?:(?:[eE])(?:(?:[+-]?)(?:[0123456789]+))|))';
|
159
|
27
|
100
|
|
|
|
183
|
if ($n=~/^\s*$real_re(.*)$/os) {
|
160
|
23
|
|
100
|
|
|
121
|
return ($1,length($2 || ''));
|
161
|
|
|
|
|
|
|
} else {
|
162
|
4
|
|
|
|
|
9
|
return (undef,length($n));
|
163
|
|
|
|
|
|
|
}
|
164
|
|
|
|
|
|
|
}
|
165
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
sub replace($$$$) # ($fmt, $len, $argref, $config)
|
167
|
|
|
|
|
|
|
{
|
168
|
161
|
|
|
161
|
0
|
189
|
my $ref = $_[2];
|
169
|
161
|
|
|
|
|
186
|
my $text = '';
|
170
|
161
|
|
|
|
|
174
|
my $rem = $_[1];
|
171
|
161
|
|
|
|
|
189
|
my $config = $_[3];
|
172
|
161
|
|
|
|
|
159
|
my $filled = 0;
|
173
|
|
|
|
|
|
|
|
174
|
161
|
50
|
|
|
|
285
|
if ($config->{fill}) { $$ref =~ s/\A\s*// }
|
|
0
|
|
|
|
|
0
|
|
175
|
161
|
|
|
|
|
523
|
else { $$ref =~ s/\A[ \t]*// }
|
176
|
|
|
|
|
|
|
|
177
|
161
|
|
|
|
|
229
|
my $fmtnum = length $_[0];
|
178
|
|
|
|
|
|
|
|
179
|
161
|
100
|
100
|
|
|
745
|
if ($$ref =~ /\S/ && $fmtnum>2)
|
180
|
|
|
|
|
|
|
{
|
181
|
54
|
|
|
|
|
102
|
NUMERICAL:{
|
182
|
25
|
|
|
|
|
27
|
my ($ilen,$dlen) = map {length} $_[0] =~ m/([]>]+)\Q$decimal\E([[<]+)/;
|
|
27
|
|
|
|
|
217
|
|
183
|
27
|
|
|
|
|
63
|
my ($num,$unconsumed) = strtod1($$ref);
|
184
|
|
|
|
|
|
|
|
185
|
27
|
100
|
|
|
|
70
|
if ($unconsumed == length $$ref)
|
186
|
|
|
|
|
|
|
{
|
187
|
4
|
|
|
|
|
12
|
$$ref =~ s/\s*\S*//;
|
188
|
4
|
100
|
66
|
|
|
26
|
redo NUMERICAL if $config->{numeric} =~ m/\bSkipNaN\b/i
|
189
|
|
|
|
|
|
|
&& $$ref =~ m/\S/;
|
190
|
2
|
|
|
|
|
7
|
$text = '?' x $ilen . $decimal . '?' x $dlen;
|
191
|
2
|
|
|
|
|
2
|
$rem = 0;
|
192
|
2
|
|
|
|
|
6
|
return $text;
|
193
|
|
|
|
|
|
|
}
|
194
|
23
|
|
|
|
|
176
|
my $formatted = sprintf "%$fmtnum.${dlen}f", $num;
|
195
|
23
|
100
|
|
|
|
58
|
$text = (length $formatted > $fmtnum)
|
196
|
|
|
|
|
|
|
? '#' x $ilen . $decimal . '#' x $dlen
|
197
|
|
|
|
|
|
|
: $formatted;
|
198
|
23
|
100
|
100
|
|
|
236
|
$text =~ s/(\Q$decimal\E\d+?)(0+)$/$1 . " " x length $2/e
|
|
7
|
|
|
|
|
29
|
|
199
|
|
|
|
|
|
|
unless $config->{numeric} =~ m/\bAllPlaces\b/i
|
200
|
|
|
|
|
|
|
|| $num =~ /\Q$decimal\E\d\d{$dlen,}$/;
|
201
|
23
|
100
|
|
|
|
36
|
if ($unconsumed)
|
202
|
|
|
|
|
|
|
{
|
203
|
20
|
50
|
|
|
|
38
|
if ($unconsumed == length $$ref)
|
204
|
0
|
|
|
|
|
0
|
{ $$ref =~ s/\A.[^0-9.+-]*// }
|
205
|
|
|
|
|
|
|
else
|
206
|
20
|
|
|
|
|
38
|
{ substr($$ref,0,-$unconsumed) = ""}
|
207
|
|
|
|
|
|
|
}
|
208
|
3
|
|
|
|
|
7
|
else { $$ref = "" }
|
209
|
23
|
|
|
|
|
45
|
$rem = 0;
|
210
|
|
|
|
|
|
|
}
|
211
|
|
|
|
|
|
|
}
|
212
|
|
|
|
|
|
|
else
|
213
|
|
|
|
|
|
|
{
|
214
|
136
|
|
|
|
|
382
|
while ($$ref =~ /\S/)
|
215
|
|
|
|
|
|
|
{
|
216
|
181
|
100
|
66
|
|
|
839
|
if (!$config->{fill} && $$ref=~s/\A[ \t]*\n//)
|
217
|
11
|
|
|
|
|
13
|
{ $filled = 2; last }
|
|
11
|
|
|
|
|
17
|
|
218
|
170
|
50
|
|
|
|
629
|
last unless $$ref =~ /\A(\s*)(\S+)(.*)\z/s;
|
219
|
170
|
|
|
|
|
436
|
my ($ws, $word, $extra) = ($1,$2,$3);
|
220
|
170
|
|
|
|
|
255
|
my $nonnl = $ws =~ /[^\n]/;
|
221
|
170
|
0
|
|
|
|
350
|
$ws =~ s/\n/$nonnl? "" : " "/ge if $config->{fill};
|
|
0
|
50
|
|
|
|
0
|
|
222
|
170
|
100
|
|
|
|
328
|
my $lead = ($config->{squeeze} ? ($ws ? " " : "") : $ws);
|
|
|
100
|
|
|
|
|
|
223
|
170
|
|
|
|
|
233
|
my $match = $lead . $word;
|
224
|
170
|
|
|
|
|
505
|
_debug "Extracted [$match]";
|
225
|
170
|
50
|
66
|
|
|
483
|
last if $text && $match =~ /\n/;
|
226
|
170
|
|
|
|
|
196
|
my $len1 = length($match);
|
227
|
170
|
100
|
|
|
|
261
|
if ($len1 <= $rem)
|
228
|
|
|
|
|
|
|
{
|
229
|
90
|
|
|
|
|
200
|
_debug "Accepted [$match]";
|
230
|
90
|
|
|
|
|
129
|
$text .= $match;
|
231
|
90
|
|
|
|
|
126
|
$rem -= $len1;
|
232
|
90
|
|
|
|
|
182
|
$$ref = $extra;
|
233
|
|
|
|
|
|
|
}
|
234
|
|
|
|
|
|
|
else
|
235
|
|
|
|
|
|
|
{
|
236
|
80
|
|
|
|
|
188
|
_debug "Need to break [$match]";
|
237
|
|
|
|
|
|
|
# was: if ($len1 > $_[1] and $rem-length($lead)>$config->{minbreak})
|
238
|
80
|
100
|
|
|
|
206
|
if ($rem-length($lead)>$config->{minbreak})
|
239
|
|
|
|
|
|
|
{
|
240
|
55
|
|
|
|
|
126
|
_debug "Trying to break '$match'";
|
241
|
55
|
|
|
|
|
137
|
my ($broken,$left) =
|
242
|
|
|
|
|
|
|
$config->{break}->($match,$rem,$_[1]);
|
243
|
55
|
|
|
|
|
81
|
$text .= $broken;
|
244
|
55
|
|
|
|
|
147
|
_debug "Broke as: [$broken][$left]";
|
245
|
55
|
|
|
|
|
98
|
$$ref = $left.$extra;
|
246
|
55
|
|
|
|
|
92
|
$rem -= length $broken;
|
247
|
|
|
|
|
|
|
}
|
248
|
80
|
|
|
|
|
134
|
last;
|
249
|
|
|
|
|
|
|
}
|
250
|
|
|
|
|
|
|
}
|
251
|
90
|
|
|
|
|
279
|
continue { $filled=1 }
|
252
|
|
|
|
|
|
|
}
|
253
|
|
|
|
|
|
|
|
254
|
159
|
100
|
100
|
|
|
588
|
if (!$filled && $rem>0 && $$ref=~/\S/ && length $text == 0)
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
255
|
|
|
|
|
|
|
{
|
256
|
6
|
|
|
|
|
78
|
$$ref =~ s/^\s*(.{1,$rem})//;
|
257
|
6
|
|
|
|
|
13
|
$text = $1;
|
258
|
6
|
|
|
|
|
13
|
$rem -= length $text;
|
259
|
|
|
|
|
|
|
}
|
260
|
|
|
|
|
|
|
|
261
|
159
|
100
|
100
|
|
|
1008
|
if ( $text=~/ / && $_[0] eq 'J' && $$ref=~/\S/ && $filled!=2 ) {
|
|
|
100
|
66
|
|
|
|
|
|
|
100
|
66
|
|
|
|
|
262
|
|
|
|
|
|
|
# FULLY JUSTIFIED
|
263
|
2
|
|
|
|
|
5
|
$text = reverse $text;
|
264
|
2
|
100
|
|
|
|
12
|
$text =~ s/( +)/($rem-->0?" ":"").$1/ge while $rem>0;
|
|
4
|
|
|
|
|
20
|
|
265
|
2
|
|
|
|
|
5
|
$text = reverse $text;
|
266
|
|
|
|
|
|
|
}
|
267
|
|
|
|
|
|
|
elsif ( $_[0] =~ /\>|\]/ ) { # RIGHT JUSTIFIED
|
268
|
42
|
100
|
|
|
|
111
|
substr($text,0,0) =
|
269
|
|
|
|
|
|
|
substr($config->{filler}{left} x $rem, -$rem)
|
270
|
|
|
|
|
|
|
if $rem > 0;
|
271
|
|
|
|
|
|
|
}
|
272
|
|
|
|
|
|
|
elsif ( $_[0] =~ /\^|\|/ ) { # CENTRE JUSTIFIED
|
273
|
6
|
100
|
|
|
|
16
|
if ($rem>0) {
|
274
|
2
|
|
|
|
|
7
|
my $halfrem = int($rem/2);
|
275
|
2
|
|
|
|
|
10
|
substr($text,0,0) =
|
276
|
|
|
|
|
|
|
substr($config->{filler}{left}x$halfrem, -$halfrem);
|
277
|
2
|
|
|
|
|
4
|
$halfrem = $rem-$halfrem;
|
278
|
2
|
|
|
|
|
6
|
$text .= substr($config->{filler}{right}x$halfrem, 0, $halfrem);
|
279
|
|
|
|
|
|
|
}
|
280
|
|
|
|
|
|
|
}
|
281
|
|
|
|
|
|
|
else { # LEFT JUSTIFIED
|
282
|
109
|
100
|
|
|
|
285
|
$text .= substr($config->{filler}{right}x$rem, 0, $rem)
|
283
|
|
|
|
|
|
|
if $rem > 0;
|
284
|
|
|
|
|
|
|
}
|
285
|
|
|
|
|
|
|
|
286
|
159
|
|
|
|
|
406
|
return $text;
|
287
|
|
|
|
|
|
|
}
|
288
|
|
|
|
|
|
|
|
289
|
|
|
|
|
|
|
my %std_config =
|
290
|
|
|
|
|
|
|
(
|
291
|
|
|
|
|
|
|
header => sub{""},
|
292
|
|
|
|
|
|
|
footer => sub{""},
|
293
|
|
|
|
|
|
|
pagefeed => sub{""},
|
294
|
|
|
|
|
|
|
pagelen => 0,
|
295
|
|
|
|
|
|
|
pagenum => undef,
|
296
|
|
|
|
|
|
|
pagewidth => 72,
|
297
|
|
|
|
|
|
|
break => break_with('-'),
|
298
|
|
|
|
|
|
|
minbreak => 2,
|
299
|
|
|
|
|
|
|
squeeze => 0,
|
300
|
|
|
|
|
|
|
filler => {left=>' ', right=>' '},
|
301
|
|
|
|
|
|
|
interleave => 0,
|
302
|
|
|
|
|
|
|
numeric => "",
|
303
|
|
|
|
|
|
|
_used => 1,
|
304
|
|
|
|
|
|
|
);
|
305
|
|
|
|
|
|
|
|
306
|
|
|
|
|
|
|
sub lcr {
|
307
|
0
|
|
|
0
|
0
|
0
|
my ($data, $pagewidth, $header) = @_;
|
308
|
0
|
|
0
|
|
|
0
|
$data->{width} ||= $pagewidth;
|
309
|
0
|
|
0
|
|
|
0
|
$data->{left} ||= "";
|
310
|
0
|
|
0
|
|
|
0
|
$data->{centre} ||= $data->{center}||"";
|
|
|
|
0
|
|
|
|
|
311
|
0
|
|
0
|
|
|
0
|
$data->{right} ||= "";
|
312
|
|
|
|
|
|
|
return sub {
|
313
|
0
|
0
|
|
0
|
|
0
|
my @l = split "\n", (ref $data->{left} eq 'CODE'
|
314
|
|
|
|
|
|
|
? $data->{left}->(@_) : $data->{left}), -1;
|
315
|
0
|
0
|
|
|
|
0
|
my @c = split "\n", (ref $data->{centre} eq 'CODE'
|
316
|
|
|
|
|
|
|
? $data->{centre}->(@_) : $data->{centre}), -1;
|
317
|
0
|
0
|
|
|
|
0
|
my @r = split "\n", (ref $data->{right} eq 'CODE'
|
318
|
|
|
|
|
|
|
? $data->{right}->(@_) : $data->{right}), -1;
|
319
|
0
|
|
|
|
|
0
|
my $text = "";
|
320
|
0
|
|
0
|
|
|
0
|
while (@l||@c||@r) {
|
|
|
|
0
|
|
|
|
|
321
|
0
|
0
|
|
|
|
0
|
my $l = @l ? shift(@l) : "";
|
322
|
0
|
0
|
|
|
|
0
|
my $c = @c ? shift(@c) : "";
|
323
|
0
|
0
|
|
|
|
0
|
my $r = @r ? shift(@r) : "";
|
324
|
0
|
|
|
|
|
0
|
my $gap = int(($data->{width}-length($c))/2-length($l));
|
325
|
0
|
0
|
|
|
|
0
|
if ($gap < 0) {
|
326
|
0
|
|
|
|
|
0
|
$gap = 0;
|
327
|
0
|
0
|
|
|
|
0
|
carpfirst "\nWarning: $header is wider than specified page width ($data->{width} chars)" if $^W;
|
328
|
|
|
|
|
|
|
}
|
329
|
0
|
|
|
|
|
0
|
$text .= $l . " " x $gap
|
330
|
|
|
|
|
|
|
. $c . " " x ($data->{width}-length($l)-length($c)-$gap-length($r))
|
331
|
|
|
|
|
|
|
. $r
|
332
|
|
|
|
|
|
|
. "\n";
|
333
|
|
|
|
|
|
|
}
|
334
|
0
|
|
|
|
|
0
|
return $text;
|
335
|
|
|
|
|
|
|
}
|
336
|
0
|
|
|
|
|
0
|
}
|
337
|
|
|
|
|
|
|
|
338
|
|
|
|
|
|
|
sub fix_config(\%)
|
339
|
|
|
|
|
|
|
{
|
340
|
24
|
|
|
24
|
0
|
34
|
my ($config) = @_;
|
341
|
24
|
50
|
|
|
|
96
|
if (ref $config->{header} eq 'HASH') {
|
|
|
50
|
|
|
|
|
|
342
|
0
|
|
|
|
|
0
|
$config->{header} =
|
343
|
|
|
|
|
|
|
lcr $config->{header}, $config->{pagewidth}, 'header';
|
344
|
|
|
|
|
|
|
}
|
345
|
|
|
|
|
|
|
elsif (ref $config->{header} eq 'CODE') {
|
346
|
24
|
|
|
|
|
36
|
my $tmp = $config->{header};
|
347
|
|
|
|
|
|
|
$config->{header} = sub {
|
348
|
30
|
|
|
30
|
|
52
|
my $header = &$tmp;
|
349
|
30
|
50
|
|
|
|
82
|
return (ref $header eq 'HASH')
|
350
|
|
|
|
|
|
|
? lcr($header,$config->{pagewidth},'header')->()
|
351
|
|
|
|
|
|
|
: $header;
|
352
|
|
|
|
|
|
|
}
|
353
|
24
|
|
|
|
|
106
|
}
|
354
|
|
|
|
|
|
|
else {
|
355
|
0
|
|
|
|
|
0
|
my $tmp = $config->{header};
|
356
|
0
|
|
|
0
|
|
0
|
$config->{header} = sub { $tmp }
|
357
|
0
|
|
|
|
|
0
|
}
|
358
|
24
|
50
|
|
|
|
85
|
if (ref $config->{footer} eq 'HASH') {
|
|
|
100
|
|
|
|
|
|
359
|
0
|
|
|
|
|
0
|
$config->{footer} =
|
360
|
|
|
|
|
|
|
lcr $config->{footer}, $config->{pagewidth}, 'footer';
|
361
|
|
|
|
|
|
|
}
|
362
|
|
|
|
|
|
|
elsif (ref $config->{footer} eq 'CODE') {
|
363
|
22
|
|
|
|
|
33
|
my $tmp = $config->{footer};
|
364
|
|
|
|
|
|
|
$config->{footer} = sub {
|
365
|
25
|
|
|
25
|
|
43
|
my $footer = &$tmp;
|
366
|
25
|
50
|
|
|
|
61
|
return (ref $footer eq 'HASH')
|
367
|
|
|
|
|
|
|
? lcr($footer,$config->{pagewidth},'footer')->()
|
368
|
|
|
|
|
|
|
: $footer;
|
369
|
|
|
|
|
|
|
}
|
370
|
22
|
|
|
|
|
107
|
}
|
371
|
|
|
|
|
|
|
else {
|
372
|
2
|
|
|
|
|
3
|
my $tmp = $config->{footer};
|
373
|
7
|
|
|
7
|
|
11
|
$config->{footer} = sub { $tmp }
|
374
|
2
|
|
|
|
|
7
|
}
|
375
|
24
|
100
|
|
|
|
90
|
unless (ref $config->{pagefeed} eq 'CODE')
|
376
|
2
|
|
|
3
|
|
4
|
{ my $tmp = $config->{pagefeed}; $config->{pagefeed} = sub { $tmp } }
|
|
2
|
|
|
|
|
8
|
|
|
3
|
|
|
|
|
5
|
|
377
|
24
|
100
|
|
|
|
63
|
unless (ref $config->{break} eq 'CODE')
|
378
|
1
|
|
|
|
|
5
|
{ $config->{break} = break_at($config->{break}) }
|
379
|
24
|
50
|
66
|
|
|
75
|
if (defined $config->{pagenum} && ref $config->{pagenum} ne 'SCALAR')
|
380
|
0
|
|
|
|
|
0
|
{ my $tmp = $config->{pagenum}+0; $config->{pagenum} = \$tmp }
|
|
0
|
|
|
|
|
0
|
|
381
|
24
|
50
|
|
|
|
64
|
unless (ref $config->{filler} eq 'HASH') {
|
382
|
0
|
|
|
|
|
0
|
$config->{filler} = { left => "$config->{filler}",
|
383
|
|
|
|
|
|
|
right => "$config->{filler}" }
|
384
|
|
|
|
|
|
|
}
|
385
|
|
|
|
|
|
|
}
|
386
|
|
|
|
|
|
|
|
387
|
|
|
|
|
|
|
sub FormOpt::DESTROY
|
388
|
|
|
|
|
|
|
{
|
389
|
1
|
50
|
33
|
1
|
|
428
|
print STDERR "\nWarning: lexical &form configuration at $std_config{_line} was never used.\n"
|
390
|
|
|
|
|
|
|
if $^W && !$std_config{_used};
|
391
|
1
|
|
|
|
|
2
|
%std_config = %{$std_config{_prev}};
|
|
1
|
|
|
|
|
17
|
|
392
|
|
|
|
|
|
|
}
|
393
|
|
|
|
|
|
|
|
394
|
|
|
|
|
|
|
sub form
|
395
|
|
|
|
|
|
|
{
|
396
|
2
|
|
|
2
|
|
23
|
use vars '%carped';
|
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
757
|
|
397
|
56
|
|
|
56
|
1
|
26525
|
local %carped;
|
398
|
56
|
|
|
|
|
569
|
my $config = {%std_config};
|
399
|
56
|
|
|
|
|
121
|
my $startidx = 0;
|
400
|
56
|
100
|
66
|
|
|
310
|
if (@_ && ref($_[0]) eq 'HASH') # RESETTING CONFIG
|
401
|
|
|
|
|
|
|
{
|
402
|
23
|
100
|
|
|
|
50
|
if (@_ > 1) # TEMPORARY RESET
|
|
|
50
|
|
|
|
|
|
403
|
|
|
|
|
|
|
{
|
404
|
22
|
|
|
|
|
82
|
$config = {%$config, %{$_[$startidx++]}};
|
|
22
|
|
|
|
|
186
|
|
405
|
22
|
|
|
|
|
118
|
fix_config(%$config);
|
406
|
22
|
|
|
|
|
37
|
$startidx = 1;
|
407
|
|
|
|
|
|
|
}
|
408
|
|
|
|
|
|
|
elsif (defined wantarray) # CONTEXT BEING CAPTURED
|
409
|
|
|
|
|
|
|
{
|
410
|
1
|
|
|
|
|
8
|
$_[0]->{_prev} = { %std_config };
|
411
|
1
|
|
|
|
|
3
|
$_[0]->{_used} = 0;
|
412
|
1
|
|
|
|
|
6
|
$_[0]->{_line} = join " line ", (caller)[1..2];;
|
413
|
1
|
|
|
|
|
5
|
%{$_[0]} = %std_config = (%std_config, %{$_[0]});
|
|
1
|
|
|
|
|
10
|
|
|
1
|
|
|
|
|
21
|
|
414
|
1
|
|
|
|
|
8
|
fix_config(%std_config);
|
415
|
1
|
|
|
|
|
7
|
return bless $_[0], 'FormOpt';
|
416
|
|
|
|
|
|
|
}
|
417
|
|
|
|
|
|
|
else # PERMANENT RESET
|
418
|
|
|
|
|
|
|
{
|
419
|
0
|
|
|
|
|
0
|
$_[0]->{_used} = 1;
|
420
|
0
|
|
|
|
|
0
|
$_[0]->{_line} = join " line ", (caller)[1..2];;
|
421
|
0
|
|
|
|
|
0
|
%std_config = (%std_config, %{$_[0]});
|
|
0
|
|
|
|
|
0
|
|
422
|
0
|
|
|
|
|
0
|
fix_config(%std_config);
|
423
|
0
|
|
|
|
|
0
|
return;
|
424
|
|
|
|
|
|
|
}
|
425
|
|
|
|
|
|
|
}
|
426
|
55
|
50
|
|
|
|
128
|
$config->{pagenum} = do{\(my $tmp=1)}
|
|
55
|
|
|
|
|
97
|
|
427
|
|
|
|
|
|
|
unless defined $config->{pagenum};
|
428
|
|
|
|
|
|
|
|
429
|
55
|
|
|
|
|
82
|
$std_config{_used}++;
|
430
|
55
|
|
|
|
|
84
|
my @ref = map { ref } @_;
|
|
142
|
|
|
|
|
323
|
|
431
|
55
|
|
|
|
|
109
|
my @orig = @_;
|
432
|
55
|
|
|
|
|
100
|
my $caller = caller;
|
433
|
2
|
|
|
2
|
|
13
|
no strict;
|
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
7517
|
|
434
|
|
|
|
|
|
|
|
435
|
55
|
|
|
|
|
132
|
for (my $nextarg=0; $nextarg<@_; $nextarg++)
|
436
|
|
|
|
|
|
|
{
|
437
|
142
|
|
|
|
|
217
|
my $next = $_[$nextarg];
|
438
|
142
|
50
|
66
|
|
|
685
|
if (!defined $next) {
|
|
|
100
|
100
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
439
|
0
|
|
|
|
|
0
|
my $tmp = "";
|
440
|
0
|
|
|
|
|
0
|
splice @_, $nextarg, 1, \$tmp;
|
441
|
|
|
|
|
|
|
}
|
442
|
|
|
|
|
|
|
elsif ($ref[$nextarg] eq 'ARRAY') {
|
443
|
5
|
|
|
|
|
29
|
splice @_, $nextarg, 1, \join("\n", @$next)
|
444
|
|
|
|
|
|
|
}
|
445
|
|
|
|
|
|
|
elsif ($ref[$nextarg] eq 'HASH' && $next->{cols} ) {
|
446
|
0
|
0
|
|
|
|
0
|
croak "Missing 'from' data for 'cols' option"
|
447
|
|
|
|
|
|
|
unless $next->{from};
|
448
|
0
|
0
|
|
|
|
0
|
croak "Can't mix other options with 'cols' option"
|
449
|
|
|
|
|
|
|
if keys %$next > 2;
|
450
|
0
|
|
|
|
|
0
|
my ($cols, $data) = @{$next}{'cols','from'};
|
|
0
|
|
|
|
|
0
|
|
451
|
0
|
0
|
0
|
|
|
0
|
croak "Invalid 'cols' option.\nExpected reference to array of column specifiers but found " . (ref($cols)||"'$cols'")
|
452
|
|
|
|
|
|
|
unless ref $cols eq 'ARRAY';
|
453
|
0
|
0
|
0
|
|
|
0
|
croak "Invalid 'from' data for 'cols' option.\nExpected reference to array of hashes or arrays but found " . (ref($data)||"'$data'")
|
454
|
|
|
|
|
|
|
unless ref $data eq 'ARRAY';
|
455
|
0
|
|
|
|
|
0
|
splice @_, $nextarg, 2, columns(@$cols,@$data);
|
456
|
0
|
|
|
|
|
0
|
splice @ref, $nextarg, 2, ('ARRAY')x@$cols;
|
457
|
0
|
|
|
|
|
0
|
$nextarg--;
|
458
|
|
|
|
|
|
|
}
|
459
|
137
|
|
|
|
|
403
|
elsif (!defined eval { local $SIG{__DIE__};
|
460
|
137
|
|
|
|
|
816
|
$_[$nextarg] = $next;
|
461
|
47
|
|
|
|
|
232
|
_debug "writeable: [$_[$nextarg]]";
|
462
|
47
|
|
|
|
|
312
|
1})
|
463
|
|
|
|
|
|
|
{
|
464
|
90
|
|
|
|
|
258
|
_debug "unwriteable: [$_[$nextarg]]";
|
465
|
90
|
|
|
|
|
161
|
my $arg = $_[$nextarg];
|
466
|
90
|
|
|
|
|
381
|
splice @_, $nextarg, 1, \$arg;
|
467
|
|
|
|
|
|
|
}
|
468
|
|
|
|
|
|
|
elsif (!$ref[$nextarg]) {
|
469
|
21
|
|
|
|
|
78
|
splice @_, $nextarg, 1, \$_[$nextarg];
|
470
|
|
|
|
|
|
|
}
|
471
|
|
|
|
|
|
|
elsif ($ref[$nextarg] ne 'HASH' and $ref[$nextarg] ne 'SCALAR')
|
472
|
|
|
|
|
|
|
{
|
473
|
1
|
|
|
|
|
4
|
splice @_, $nextarg, 1, \"$next";
|
474
|
|
|
|
|
|
|
}
|
475
|
|
|
|
|
|
|
}
|
476
|
|
|
|
|
|
|
|
477
|
55
|
|
|
|
|
69
|
my $header = $config->{header}->(${$config->{pagenum}});
|
|
55
|
|
|
|
|
145
|
|
478
|
55
|
100
|
66
|
|
|
166
|
$header.="\n" if $header && substr($header,-1,1) ne "\n";
|
479
|
|
|
|
|
|
|
|
480
|
55
|
|
|
|
|
59
|
my $footer = $config->{footer}->(${$config->{pagenum}});
|
|
55
|
|
|
|
|
142
|
|
481
|
55
|
100
|
66
|
|
|
128
|
$footer.="\n" if $footer && substr($footer,-1,1) ne "\n";
|
482
|
|
|
|
|
|
|
|
483
|
55
|
|
|
|
|
75
|
my $prevfooter = $footer;
|
484
|
|
|
|
|
|
|
|
485
|
55
|
|
|
|
|
102
|
my $linecount = $header=~tr/\n/\n/ + $footer=~tr/\n/\n/;
|
486
|
55
|
|
|
|
|
63
|
my $hfcount = $linecount;
|
487
|
|
|
|
|
|
|
|
488
|
55
|
|
|
|
|
65
|
my $text = $header;
|
489
|
55
|
|
|
|
|
56
|
my @format_stack;
|
490
|
|
|
|
|
|
|
|
491
|
55
|
|
66
|
|
|
141
|
LINE: while ($startidx < @_ || @format_stack)
|
492
|
|
|
|
|
|
|
{
|
493
|
60
|
100
|
100
|
|
|
287
|
if (($ref[$startidx]||'') eq 'HASH')
|
494
|
|
|
|
|
|
|
{
|
495
|
1
|
|
|
|
|
6
|
$config = {%$config, %{$_[$startidx++]}};
|
|
1
|
|
|
|
|
8
|
|
496
|
1
|
|
|
|
|
7
|
fix_config(%$config);
|
497
|
1
|
|
|
|
|
3
|
next;
|
498
|
|
|
|
|
|
|
}
|
499
|
59
|
50
|
|
|
|
110
|
unless (@format_stack) {
|
500
|
|
|
|
|
|
|
@format_stack = $config->{interleave}
|
501
|
|
|
|
|
|
|
? map "$_\n", split /\n/, ${$_[$startidx++]}||""
|
502
|
59
|
50
|
0
|
|
|
127
|
: ${$_[$startidx++]}||"";
|
|
|
|
50
|
|
|
|
|
503
|
|
|
|
|
|
|
}
|
504
|
59
|
|
|
|
|
97
|
my $format = shift @format_stack;
|
505
|
59
|
|
|
|
|
154
|
_debug("format: [$format]");
|
506
|
|
|
|
|
|
|
|
507
|
59
|
|
|
|
|
882
|
my @parts = split /(\n|(?:\\.)+|$fieldpat)/, $format;
|
508
|
59
|
50
|
33
|
|
|
312
|
push @parts, "\n" unless @parts && $parts[-1] eq "\n";
|
509
|
59
|
|
|
|
|
72
|
my $fieldcount = 0;
|
510
|
59
|
|
|
|
|
64
|
my $filled = 0;
|
511
|
59
|
|
|
|
|
58
|
my $firstline = 1;
|
512
|
59
|
|
|
|
|
95
|
while (!$filled)
|
513
|
|
|
|
|
|
|
{
|
514
|
151
|
|
|
|
|
168
|
my $nextarg = $startidx;
|
515
|
151
|
|
|
|
|
150
|
my @data;
|
516
|
151
|
|
|
|
|
194
|
foreach my $part ( @parts )
|
517
|
|
|
|
|
|
|
{
|
518
|
553
|
100
|
100
|
|
|
6629
|
if ($part =~ /\A(?:\\.)+/)
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
519
|
|
|
|
|
|
|
{
|
520
|
2
|
|
|
|
|
7
|
_debug("esc literal: [$part]");
|
521
|
2
|
|
|
|
|
3
|
my $tmp = $part;
|
522
|
2
|
|
|
|
|
20
|
$tmp =~ s/\\(.)/$1/g;
|
523
|
2
|
|
|
|
|
4
|
$text .= $tmp;
|
524
|
|
|
|
|
|
|
}
|
525
|
|
|
|
|
|
|
elsif ($part =~ /($lfieldmark)/)
|
526
|
|
|
|
|
|
|
{
|
527
|
21
|
100
|
|
|
|
38
|
if ($firstline)
|
528
|
|
|
|
|
|
|
{
|
529
|
20
|
|
|
|
|
22
|
$fieldcount++;
|
530
|
20
|
50
|
|
|
|
49
|
if ($nextarg > $#_)
|
531
|
0
|
|
|
|
|
0
|
{ push @_,\$emptyref; push @ref, '' }
|
|
0
|
|
|
|
|
0
|
|
532
|
20
|
|
|
|
|
39
|
my $type = $1;
|
533
|
20
|
100
|
|
|
|
73
|
$type = 'J' if $part =~ /$ljustified/;
|
534
|
20
|
100
|
|
|
|
48
|
croak BAD_CONFIG if ($ref[$startidx] eq 'HASH');
|
535
|
19
|
|
|
|
|
51
|
_debug("once field: [$part]");
|
536
|
19
|
|
|
|
|
22
|
_debug("data was: [${$_[$nextarg]}]");
|
|
19
|
|
|
|
|
62
|
|
537
|
19
|
|
|
|
|
52
|
$text .= replace($type,length($part),$_[$nextarg],$config);
|
538
|
19
|
|
|
|
|
25
|
_debug("data now: [${$_[$nextarg]}]");
|
|
19
|
|
|
|
|
54
|
|
539
|
|
|
|
|
|
|
}
|
540
|
|
|
|
|
|
|
else
|
541
|
|
|
|
|
|
|
{
|
542
|
1
|
|
|
|
|
5
|
$text .= substr($config->{filler}{left} x length($part), -length($part));
|
543
|
1
|
|
|
|
|
5
|
_debug("missing once field: [$part]");
|
544
|
|
|
|
|
|
|
}
|
545
|
20
|
|
|
|
|
28
|
$nextarg++;
|
546
|
|
|
|
|
|
|
}
|
547
|
|
|
|
|
|
|
elsif ($part =~ /($fieldmark)/ and substr($part,0,2) ne '~~')
|
548
|
|
|
|
|
|
|
{
|
549
|
142
|
100
|
|
|
|
306
|
$fieldcount++ if $firstline;
|
550
|
142
|
50
|
|
|
|
283
|
if ($nextarg > $#_)
|
551
|
0
|
|
|
|
|
0
|
{ push @_,\$emptyref; push @ref, '' }
|
|
0
|
|
|
|
|
0
|
|
552
|
142
|
|
|
|
|
278
|
my $type = $1;
|
553
|
142
|
100
|
|
|
|
387
|
$type = 'J' if $part =~ /$bjustified/;
|
554
|
142
|
50
|
|
|
|
282
|
croak BAD_CONFIG if ($ref[$startidx] eq 'HASH');
|
555
|
142
|
|
|
|
|
352
|
_debug("multi field: [$part]");
|
556
|
142
|
|
|
|
|
159
|
_debug("data was: [${$_[$nextarg]}]");
|
|
142
|
|
|
|
|
423
|
|
557
|
142
|
|
|
|
|
364
|
$text .= replace($type,length($part),$_[$nextarg],$config);
|
558
|
142
|
|
|
|
|
233
|
_debug("data now: [${$_[$nextarg]}]");
|
|
142
|
|
|
|
|
438
|
|
559
|
142
|
|
|
|
|
359
|
push @data, $_[$nextarg];
|
560
|
142
|
|
|
|
|
180
|
$nextarg++;
|
561
|
|
|
|
|
|
|
}
|
562
|
|
|
|
|
|
|
else
|
563
|
|
|
|
|
|
|
{
|
564
|
388
|
|
|
|
|
935
|
_debug("literal: [$part]");
|
565
|
388
|
|
|
|
|
518
|
my $tmp = $part;
|
566
|
388
|
|
|
|
|
478
|
$tmp =~ s/\0(\0*)/$1/g;
|
567
|
388
|
|
|
|
|
419
|
$text .= $tmp;
|
568
|
388
|
100
|
|
|
|
909
|
if ($part eq "\n")
|
569
|
|
|
|
|
|
|
{
|
570
|
153
|
|
|
|
|
156
|
$linecount++;
|
571
|
153
|
100
|
100
|
|
|
449
|
if ($config->{pagelen} && $linecount>=$config->{pagelen})
|
572
|
|
|
|
|
|
|
{
|
573
|
5
|
|
|
|
|
15
|
_debug("\tejecting page: $config->{pagenum}");
|
574
|
5
|
50
|
33
|
|
|
39
|
carpfirst "\nWarning: could not format page ${$config->{pagenum}} within specified page length"
|
|
0
|
|
33
|
|
|
0
|
|
575
|
|
|
|
|
|
|
if $^W && $config->{pagelen} && $linecount > $config->{pagelen};
|
576
|
5
|
|
|
|
|
6
|
${$config->{pagenum}}++;
|
|
5
|
|
|
|
|
8
|
|
577
|
5
|
|
|
|
|
7
|
my $pagefeed = $config->{pagefeed}->(${$config->{pagenum}});
|
|
5
|
|
|
|
|
13
|
|
578
|
5
|
|
|
|
|
6
|
$header = $config->{header}->(${$config->{pagenum}});
|
|
5
|
|
|
|
|
12
|
|
579
|
5
|
100
|
66
|
|
|
24
|
$header.="\n" if $header && substr($header,-1,1) ne "\n";
|
580
|
5
|
|
|
|
|
9
|
$text .= $footer
|
581
|
|
|
|
|
|
|
. $pagefeed
|
582
|
|
|
|
|
|
|
. $header;
|
583
|
5
|
|
|
|
|
7
|
$prevfooter = $footer;
|
584
|
5
|
|
|
|
|
4
|
$footer = $config->{footer}->(${$config->{pagenum}});
|
|
5
|
|
|
|
|
12
|
|
585
|
5
|
100
|
66
|
|
|
21
|
$footer.="\n" if $footer && substr($footer,-1,1) ne "\n";
|
586
|
5
|
|
|
|
|
8
|
$linecount = $hfcount =
|
587
|
|
|
|
|
|
|
$header=~tr/\n/\n/ + $footer=~tr/\n/\n/;
|
588
|
5
|
|
|
|
|
20
|
$header = $pagefeed
|
589
|
|
|
|
|
|
|
. $header;
|
590
|
|
|
|
|
|
|
}
|
591
|
|
|
|
|
|
|
}
|
592
|
|
|
|
|
|
|
}
|
593
|
552
|
|
|
|
|
1300
|
_debug("\tnextarg now: $nextarg");
|
594
|
552
|
|
|
|
|
1415
|
_debug("\tstartidx now: $startidx");
|
595
|
|
|
|
|
|
|
}
|
596
|
150
|
|
|
|
|
201
|
$firstline = 0;
|
597
|
150
|
|
|
|
|
272
|
$filled = ! grep { notempty $_ } @data;
|
|
142
|
|
|
|
|
230
|
|
598
|
|
|
|
|
|
|
}
|
599
|
58
|
|
|
|
|
330
|
$startidx += $fieldcount;
|
600
|
|
|
|
|
|
|
}
|
601
|
|
|
|
|
|
|
|
602
|
|
|
|
|
|
|
# ADJUST FINAL PAGE HEADER OR FOOTER AS REQUIRED
|
603
|
54
|
100
|
100
|
|
|
317
|
if ($hfcount && $linecount == $hfcount) # UNNEEDED HEADER
|
|
|
100
|
100
|
|
|
|
|
604
|
|
|
|
|
|
|
{
|
605
|
1
|
|
|
|
|
21
|
$text =~ s/\Q$header\E\Z//;
|
606
|
|
|
|
|
|
|
}
|
607
|
|
|
|
|
|
|
elsif ($linecount && $config->{pagelen}) # MISSING FOOTER
|
608
|
|
|
|
|
|
|
{
|
609
|
3
|
|
|
|
|
8
|
$text .= "\n" x ($config->{pagelen}-$linecount)
|
610
|
|
|
|
|
|
|
. $footer;
|
611
|
3
|
|
|
|
|
5
|
$prevfooter = $footer;
|
612
|
|
|
|
|
|
|
}
|
613
|
|
|
|
|
|
|
|
614
|
|
|
|
|
|
|
# REPLACE LAST FOOTER
|
615
|
|
|
|
|
|
|
|
616
|
54
|
100
|
|
|
|
108
|
if ($prevfooter) {
|
617
|
2
|
|
|
|
|
3
|
my $lastfooter = $config->{footer}->(${$config->{pagenum}},1);
|
|
2
|
|
|
|
|
6
|
|
618
|
2
|
50
|
33
|
|
|
14
|
$lastfooter.="\n"
|
619
|
|
|
|
|
|
|
if $lastfooter && substr($lastfooter,-1,1) ne "\n";
|
620
|
2
|
|
|
|
|
11
|
my $footerdiff = ($lastfooter =~ tr/\n/\n/)
|
621
|
|
|
|
|
|
|
- ($prevfooter =~ tr/\n/\n/);
|
622
|
|
|
|
|
|
|
# Enough space to squeeze longer final footer in?
|
623
|
2
|
|
|
|
|
5
|
my $tail = '^[^\S\n]*\n' x $footerdiff;
|
624
|
2
|
50
|
33
|
|
|
6
|
if ($footerdiff > 0 && $text =~ /($tail\Q$prevfooter\E)\Z/m) {
|
625
|
0
|
|
|
|
|
0
|
$prevfooter = $1;
|
626
|
0
|
|
|
|
|
0
|
$footerdiff = 0;
|
627
|
|
|
|
|
|
|
}
|
628
|
|
|
|
|
|
|
# Apparently, not, so create an extra (empty) page for it
|
629
|
2
|
50
|
|
|
|
6
|
if ($footerdiff > 0) {
|
630
|
0
|
|
|
|
|
0
|
${$config->{pagenum}}++;
|
|
0
|
|
|
|
|
0
|
|
631
|
0
|
|
|
|
|
0
|
my $lastheader = $config->{header}->(${$config->{pagenum}});
|
|
0
|
|
|
|
|
0
|
|
632
|
0
|
0
|
0
|
|
|
0
|
$lastheader.="\n"
|
633
|
|
|
|
|
|
|
if $lastheader && substr($lastheader,-1,1) ne "\n";
|
634
|
0
|
|
|
|
|
0
|
$lastfooter = $config->{footer}->(${$config->{pagenum}},1);
|
|
0
|
|
|
|
|
0
|
|
635
|
0
|
0
|
0
|
|
|
0
|
$lastfooter.="\n"
|
636
|
|
|
|
|
|
|
if $lastfooter && substr($lastfooter,-1,1) ne "\n";
|
637
|
|
|
|
|
|
|
|
638
|
0
|
|
|
|
|
0
|
$text .= $lastheader
|
639
|
|
|
|
|
|
|
. ("\n" x ( $config->{pagelen}
|
640
|
|
|
|
|
|
|
- ($lastheader =~ tr/\n/\n/)
|
641
|
|
|
|
|
|
|
- ($lastfooter =~ tr/\n/\n/)
|
642
|
|
|
|
|
|
|
)
|
643
|
|
|
|
|
|
|
)
|
644
|
|
|
|
|
|
|
. $lastfooter;
|
645
|
|
|
|
|
|
|
}
|
646
|
|
|
|
|
|
|
else {
|
647
|
2
|
|
|
|
|
5
|
$lastfooter = ("\n"x-$footerdiff).$lastfooter;
|
648
|
2
|
|
|
|
|
6
|
substr($text, -length($prevfooter)) = $lastfooter;
|
649
|
|
|
|
|
|
|
}
|
650
|
|
|
|
|
|
|
}
|
651
|
|
|
|
|
|
|
|
652
|
|
|
|
|
|
|
# RESTORE ARG LIST
|
653
|
54
|
|
|
|
|
120
|
for my $i (0..$#orig)
|
654
|
|
|
|
|
|
|
{
|
655
|
139
|
100
|
|
|
|
373
|
if ($ref[$i] eq 'ARRAY')
|
|
|
100
|
|
|
|
|
|
656
|
5
|
|
|
|
|
6
|
{ eval { @{$orig[$i]} = map "$_\n", split /\n/, ${$_[$i]} } }
|
|
5
|
|
|
|
|
6
|
|
|
5
|
|
|
|
|
17
|
|
|
5
|
|
|
|
|
12
|
|
657
|
|
|
|
|
|
|
elsif (!$ref[$i])
|
658
|
109
|
50
|
|
|
|
124
|
{ eval { _debug("restoring $i (".$_[$i].") to " .
|
|
109
|
|
|
|
|
460
|
|
659
|
|
|
|
|
|
|
defined($orig[$i]) ? $orig[$i] : "");
|
660
|
109
|
|
|
|
|
135
|
${$_[$i]} = $orig[$i] } }
|
|
109
|
|
|
|
|
323
|
|
661
|
|
|
|
|
|
|
}
|
662
|
|
|
|
|
|
|
|
663
|
54
|
|
|
|
|
77
|
${$config->{pagenum}}++;
|
|
54
|
|
|
|
|
95
|
|
664
|
54
|
50
|
|
|
|
114
|
$text =~ s/[ ]+$//gm if $config->{trim};
|
665
|
54
|
50
|
|
|
|
436
|
return $text unless wantarray;
|
666
|
0
|
|
|
|
|
0
|
return map "$_\n", split /\n/, $text;
|
667
|
|
|
|
|
|
|
}
|
668
|
|
|
|
|
|
|
|
669
|
|
|
|
|
|
|
|
670
|
|
|
|
|
|
|
#==== columns ========================================#
|
671
|
|
|
|
|
|
|
|
672
|
|
|
|
|
|
|
sub columns {
|
673
|
0
|
|
|
0
|
0
|
0
|
my @cols;
|
674
|
0
|
|
|
|
|
0
|
my (@fullres, @res);
|
675
|
0
|
|
|
|
|
0
|
while (@_) {
|
676
|
0
|
|
|
|
|
0
|
my $arg = shift @_;
|
677
|
0
|
|
|
|
|
0
|
my $type = ref $arg;
|
678
|
0
|
0
|
|
|
|
0
|
if ($type eq 'HASH') {
|
|
|
0
|
|
|
|
|
|
679
|
0
|
|
|
|
|
0
|
push @{$res[$_]}, $arg->{$cols[$_]} for 0..$#cols;
|
|
0
|
|
|
|
|
0
|
|
680
|
|
|
|
|
|
|
}
|
681
|
|
|
|
|
|
|
elsif ($type eq 'ARRAY') {
|
682
|
0
|
|
|
|
|
0
|
push @{$res[$_]}, $arg->[$cols[$_]] for 0..$#cols;
|
|
0
|
|
|
|
|
0
|
|
683
|
|
|
|
|
|
|
}
|
684
|
|
|
|
|
|
|
else {
|
685
|
0
|
0
|
|
|
|
0
|
if (@res) {
|
686
|
0
|
|
|
|
|
0
|
push @fullres, @res;
|
687
|
0
|
|
|
|
|
0
|
@res = @cols = ();
|
688
|
|
|
|
|
|
|
}
|
689
|
0
|
|
|
|
|
0
|
push @cols, $arg;
|
690
|
|
|
|
|
|
|
}
|
691
|
|
|
|
|
|
|
}
|
692
|
0
|
|
|
|
|
0
|
return @fullres, @res;
|
693
|
|
|
|
|
|
|
}
|
694
|
|
|
|
|
|
|
|
695
|
|
|
|
|
|
|
|
696
|
|
|
|
|
|
|
#==== tag ============================================#
|
697
|
|
|
|
|
|
|
|
698
|
|
|
|
|
|
|
sub invert($)
|
699
|
|
|
|
|
|
|
{
|
700
|
7
|
|
|
7
|
0
|
12
|
my $inversion = reverse $_[0];
|
701
|
7
|
|
|
|
|
25
|
$inversion =~ tr/{[<(/}]>)/;
|
702
|
7
|
|
|
|
|
22
|
return $inversion;
|
703
|
|
|
|
|
|
|
}
|
704
|
|
|
|
|
|
|
|
705
|
|
|
|
|
|
|
sub tag # ($tag, $text; $opt_endtag)
|
706
|
|
|
|
|
|
|
{
|
707
|
7
|
|
|
7
|
1
|
2767
|
my ($tagleader,$tagindent,$ldelim,$tag,$tagargs,$tagtrailer) =
|
708
|
|
|
|
|
|
|
( $_[0] =~ /\A((?:[ \t]*\n)*)([ \t]*)(\W*)(\w+)(.*?)(\s*)\Z/ );
|
709
|
|
|
|
|
|
|
|
710
|
7
|
100
|
|
|
|
23
|
$ldelim = '<' unless $ldelim;
|
711
|
7
|
|
|
|
|
27
|
$tagtrailer =~ s/([ \t]*)\Z//;
|
712
|
7
|
|
100
|
|
|
36
|
my $textindent = $1||"";
|
713
|
|
|
|
|
|
|
|
714
|
7
|
|
|
|
|
14
|
my $rdelim = invert $ldelim;
|
715
|
|
|
|
|
|
|
|
716
|
7
|
|
|
|
|
10
|
my $i;
|
717
|
7
|
|
100
|
|
|
46
|
for ($i = -1; -1-$i < length $rdelim && -1-$i < length $tagargs; $i--)
|
718
|
|
|
|
|
|
|
{
|
719
|
5
|
100
|
|
|
|
24
|
last unless substr($tagargs,$i,1) eq substr($rdelim,$i,1);
|
720
|
|
|
|
|
|
|
}
|
721
|
7
|
100
|
|
|
|
15
|
if ($i < -1)
|
722
|
|
|
|
|
|
|
{
|
723
|
3
|
|
|
|
|
4
|
$i++;
|
724
|
3
|
|
|
|
|
6
|
$tagargs = substr($tagargs,0,$i);
|
725
|
3
|
|
|
|
|
5
|
$rdelim = substr($rdelim,$i);
|
726
|
|
|
|
|
|
|
}
|
727
|
|
|
|
|
|
|
|
728
|
7
|
|
33
|
|
|
26
|
my $endtag = $_[2] || "$ldelim/$tag$rdelim";
|
729
|
|
|
|
|
|
|
|
730
|
17
|
|
|
|
|
62
|
return "$tagleader$tagindent$ldelim$tag$tagargs$rdelim$tagtrailer".
|
731
|
7
|
|
|
|
|
28
|
join("\n",map { "$tagindent$textindent$_" } split /\n/, $_[1]).
|
732
|
|
|
|
|
|
|
"$tagtrailer$tagindent$endtag$tagleader";
|
733
|
|
|
|
|
|
|
|
734
|
|
|
|
|
|
|
}
|
735
|
|
|
|
|
|
|
|
736
|
|
|
|
|
|
|
|
737
|
|
|
|
|
|
|
1;
|
738
|
|
|
|
|
|
|
|
739
|
|
|
|
|
|
|
__END__
|