|  line  | 
 stmt  | 
 bran  | 
 cond  | 
 sub  | 
 pod  | 
 time  | 
 code  | 
| 
1
 | 
  
 
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 package DBIx::XHTML_Table;  | 
| 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
3
 | 
7
 | 
 
 | 
 
 | 
  
7
  
 | 
 
 | 
54272
 | 
 use strict;  | 
| 
 
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
11
 | 
    | 
| 
 
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
198
 | 
    | 
| 
4
 | 
7
 | 
 
 | 
 
 | 
  
7
  
 | 
 
 | 
27
 | 
 use warnings;  | 
| 
 
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
9
 | 
    | 
| 
 
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
254
 | 
    | 
| 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 our $VERSION = '1.46';  | 
| 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
7
 | 
7
 | 
 
 | 
 
 | 
  
7
  
 | 
 
 | 
10227
 | 
 use DBI;  | 
| 
 
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
99550
 | 
    | 
| 
 
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
432
 | 
    | 
| 
8
 | 
7
 | 
 
 | 
 
 | 
  
7
  
 | 
 
 | 
62
 | 
 use Carp;  | 
| 
 
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
9
 | 
    | 
| 
 
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
463
 | 
    | 
| 
9
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # GLOBALS  | 
| 
11
 | 
7
 | 
 
 | 
 
 | 
  
7
  
 | 
 
 | 
32
 | 
 use vars qw(%ESCAPES $T $N);  | 
| 
 
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
7
 | 
    | 
| 
 
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
36995
 | 
    | 
| 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 ($T,$N)  = ("\t","\n");  | 
| 
13
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 %ESCAPES = (  | 
| 
14
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     '&' => '&',  | 
| 
15
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     '<' => '<',  | 
| 
16
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     '>' => '>',  | 
| 
17
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     '"' => '"',  | 
| 
18
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 );  | 
| 
19
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #################### CONSTRUCTOR ###################################  | 
| 
21
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
22
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # see POD for documentation  | 
| 
23
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub new {  | 
| 
24
 | 
2
 | 
 
 | 
 
 | 
  
2
  
 | 
  
1
  
 | 
97
 | 
     my $class = shift;  | 
| 
25
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
9
 | 
     my $self  = {  | 
| 
26
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         null_value => ' ',  | 
| 
27
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     };  | 
| 
28
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6
 | 
     bless $self, $class;  | 
| 
29
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
30
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # last arg might be GTCH (global table config hash)  | 
| 
31
 | 
2
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
13
 | 
     $self->{'global'} = pop if ref $_[$#_] eq 'HASH';  | 
| 
32
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
33
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # note: disconnected handles aren't caught :(  | 
| 
34
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
35
 | 
2
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
18
 | 
     if (UNIVERSAL::isa($_[0],'DBI::db')) {  | 
| 
 
 | 
 
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
36
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         # use supplied db handle  | 
| 
37
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         $self->{'dbh'}        = $_[0];  | 
| 
38
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         $self->{'keep_alive'} = 1;  | 
| 
39
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }   | 
| 
40
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     elsif (ref($_[0]) eq 'ARRAY') {  | 
| 
41
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         # go ahead and accept a pre-built 2d array ref  | 
| 
42
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
12
 | 
         $self->_do_black_magic(@_);  | 
| 
43
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
44
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     else {  | 
| 
45
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         # create my own db handle  | 
| 
46
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         eval { $self->{'dbh'} = DBI->connect(@_) };  | 
| 
 
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
47
 | 
  
0
  
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
0
 | 
         carp $@ and return undef if $@;  | 
| 
48
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
49
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
50
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
7
 | 
     return $self;  | 
| 
51
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
52
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
53
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #################### OBJECT METHODS ################################  | 
| 
54
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
55
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub exec_query {  | 
| 
56
 | 
  
0
  
 | 
 
 | 
 
 | 
  
0
  
 | 
  
1
  
 | 
0
 | 
     my ($self,$sql,$vars) = @_;  | 
| 
57
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
58
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     carp "can't call exec_query(): do database handle" unless $self->{'dbh'};  | 
| 
59
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
60
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     eval {  | 
| 
61
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         $self->{'sth'} = (UNIVERSAL::isa($sql,'DBI::st'))  | 
| 
62
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             ? $sql  | 
| 
63
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
             : $self->{'dbh'}->prepare($sql)  | 
| 
64
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         ;  | 
| 
65
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         $self->{'sth'}->execute(@$vars);  | 
| 
66
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     };  | 
| 
67
 | 
  
0
  
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
0
 | 
     carp $@ and return undef if $@;  | 
| 
68
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
69
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # store the results  | 
| 
70
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     $self->{'fields_arry'} = [ @{$self->{'sth'}->{'NAME'}} ];  | 
| 
 
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
71
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     $self->{'fields_hash'} = $self->_reset_fields_hash();  | 
| 
72
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     $self->{'rows'}        = $self->{'sth'}->fetchall_arrayref();  | 
| 
73
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     carp "can't call exec_query(): no data was returned from query" unless @{$self->{'rows'}};  | 
| 
 
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
74
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
75
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     if (exists $self->{'pk'}) {  | 
| 
76
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         # remove the primary key info from the arry and hash  | 
| 
77
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         $self->{'pk_index'} = delete $self->{'fields_hash'}->{$self->{'pk'}};  | 
| 
78
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         splice(@{$self->{'fields_arry'}},$self->{'pk_index'},1) if defined $self->{'pk_index'};  | 
| 
 
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
79
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
80
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
81
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     return $self;  | 
| 
82
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
83
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
84
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub output {  | 
| 
85
 | 
7
 | 
 
 | 
 
 | 
  
7
  
 | 
  
1
  
 | 
354
 | 
     my ($self,$config,$no_ws) = @_;  | 
| 
86
 | 
7
 | 
  
 50
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
25
 | 
     carp "can't call output(): no data" and return '' unless $self->{'rows'};  | 
| 
87
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
88
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # have to deprecate old arguments ...  | 
| 
89
 | 
7
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
15
 | 
     if ($no_ws) {  | 
| 
90
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         carp "scalar arguments to output() are deprecated, use hash reference";  | 
| 
91
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         $N = $T = '';  | 
| 
92
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
93
 | 
7
 | 
  
 50
  
 | 
  
 33
  
 | 
 
 | 
 
 | 
49
 | 
     if ($config and not ref $config) {  | 
| 
 
 | 
 
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
94
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         carp "scalar arguments to output() are deprecated, use hash reference";  | 
| 
95
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         $self->{'no_head'} = $config;  | 
| 
96
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
97
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     elsif ($config) {  | 
| 
98
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
18
 | 
         $self->{'no_head'}    = $config->{'no_head'};  | 
| 
99
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
11
 | 
         $self->{'no_ucfirst'} = $config->{'no_ucfirst'};  | 
| 
100
 | 
7
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
23
 | 
         $N = $T = ''         if $config->{'no_indent'};  | 
| 
101
 | 
7
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
19
 | 
         if ($config->{'no_whitespace'}) {  | 
| 
102
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
             carp "no_whitespace attrib deprecated, use no_indent";  | 
| 
103
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
             $N = $T = '';  | 
| 
104
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
105
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
106
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
107
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
17
 | 
     return $self->_build_table();  | 
| 
108
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
109
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
110
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub modify {  | 
| 
111
 | 
1
 | 
 
 | 
 
 | 
  
1
  
 | 
  
1
  
 | 
2
 | 
     my ($self,$tag,$attribs,$cols) = @_;  | 
| 
112
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
     $tag = lc $tag;  | 
| 
113
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
114
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # apply attributes to specified columns  | 
| 
115
 | 
1
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
4
 | 
     if (ref $attribs eq 'HASH') {  | 
| 
116
 | 
1
 | 
  
 50
  
 | 
  
 33
  
 | 
 
 | 
 
 | 
6
 | 
         $cols = 'global' unless defined( $cols) && length( $cols );  | 
| 
117
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
         $cols = $self->_refinate($cols);  | 
| 
118
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
119
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6
 | 
         while (my($attr,$val) = each %$attribs) {  | 
| 
120
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
7
 | 
             $self->{lc $_}->{$tag}->{$attr} = $val for @$cols;  | 
| 
121
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
122
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
123
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # or handle a special case (e.g. )  | 
| 
124
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     else {  | 
| 
125
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         # cols is really attribs now, attribs is just a scalar  | 
| 
126
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         $self->{'global'}->{$tag} = $attribs;  | 
| 
127
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
128
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         # there is only one caption - no need to rotate attribs  | 
| 
129
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         if (ref $cols->{'style'} eq 'HASH') {  | 
| 
130
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
             $cols->{'style'} = join('; ',map { "$_: ".$cols->{'style'}->{$_} } sort keys %{$cols->{'style'}}) . ';';  | 
| 
 
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
 
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
131
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
132
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
133
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         $self->{'global'}->{$tag."_attribs"} = $cols;  | 
| 
134
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
135
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
136
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
     return $self;  | 
| 
137
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
138
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
139
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub map_cell {  | 
| 
140
 | 
  
0
  
 | 
 
 | 
 
 | 
  
0
  
 | 
  
1
  
 | 
0
 | 
     my ($self,$sub,$cols) = @_;  | 
| 
141
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
142
 | 
  
0
  
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
0
 | 
     carp "map_cell() is being ignored - no data" and return $self unless $self->{'rows'};  | 
| 
143
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
144
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     $cols = $self->_refinate($cols);  | 
| 
145
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     for (@$cols) {  | 
| 
146
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         my $key;  | 
| 
147
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         if (defined $self->{'fields_hash'}->{$_}) {  | 
| 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
148
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
             $key = $_;  | 
| 
149
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         } elsif( defined $self->{'fields_hash'}->{lc $_}) {  | 
| 
150
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
             $key = lc $_;  | 
| 
151
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         } else {  | 
| 
152
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
             SEARCH: for my $k (sort keys %{ $self->{'fields_hash'} }) {  | 
| 
 
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
153
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
                 if (lc( $k ) eq lc( $_ )) {  | 
| 
154
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
                     $key = $k;  | 
| 
155
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
                     last SEARCH;  | 
| 
156
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 }  | 
| 
157
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             }  | 
| 
158
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
159
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         next unless $key;  | 
| 
160
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         $self->{'map_cell'}->{$key} = $sub;  | 
| 
161
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
162
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     return $self;  | 
| 
163
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
164
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
165
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub map_head {  | 
| 
166
 | 
1
 | 
 
 | 
 
 | 
  
1
  
 | 
  
1
  
 | 
3
 | 
     my ($self,$sub,$cols) = @_;  | 
| 
167
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
168
 | 
1
 | 
  
 50
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
3
 | 
     carp "map_head() is being ignored - no data" and return $self unless $self->{'rows'};  | 
| 
169
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
170
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5
 | 
     $cols = $self->_refinate($cols);  | 
| 
171
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
     for (@$cols) {  | 
| 
172
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1
 | 
         my $key;  | 
| 
173
 | 
1
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
4
 | 
         if (defined $self->{'fields_hash'}->{$_}) {  | 
| 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
174
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
             $key = $_;  | 
| 
175
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         } elsif( defined $self->{'fields_hash'}->{lc $_}) {  | 
| 
176
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
             $key = lc $_;  | 
| 
177
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         } else {  | 
| 
178
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
             SEARCH: for my $k (sort keys %{ $self->{'fields_hash'} }) {  | 
| 
 
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
179
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
                 if (lc( $k ) eq lc( $_ )) {  | 
| 
180
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
                     $key = $k;  | 
| 
181
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
                     last SEARCH;  | 
| 
182
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 }  | 
| 
183
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             }  | 
| 
184
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
185
 | 
1
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
2
 | 
         next unless $key;  | 
| 
186
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
         $self->{'map_head'}->{$key} = $sub;  | 
| 
187
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
188
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
189
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
     return $self;  | 
| 
190
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
191
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
192
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub add_col_tag {  | 
| 
193
 | 
  
0
  
 | 
 
 | 
 
 | 
  
0
  
 | 
  
1
  
 | 
0
 | 
     my ($self,$attribs) = @_;  | 
| 
194
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     $self->{'global'}->{'colgroup'} = {} unless $self->{'colgroups'};  | 
| 
195
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     push @{$self->{'colgroups'}}, $attribs;  | 
| 
 
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
196
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
197
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     return $self;  | 
| 
198
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
199
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
200
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub calc_totals {  | 
| 
201
 | 
1
 | 
 
 | 
 
 | 
  
1
  
 | 
  
1
  
 | 
3
 | 
     my ($self,$cols,$mask) = @_;  | 
| 
202
 | 
1
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
4
 | 
     return undef unless $self->{'rows'};  | 
| 
203
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
204
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1
 | 
     $self->{'totals_mask'} = $mask;  | 
| 
205
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
     $cols = $self->_refinate($cols);  | 
| 
206
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
207
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1
 | 
     my @indexes;  | 
| 
208
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
     for (@$cols) {  | 
| 
209
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1
 | 
         my $index;  | 
| 
210
 | 
1
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
3
 | 
         if (exists $self->{'fields_hash'}->{$_}) {  | 
| 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
211
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
             $index = $self->{'fields_hash'}->{$_};      | 
| 
212
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         } elsif (exists $self->{'fields_hash'}->{lc $_}) {  | 
| 
213
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
             $index = $self->{'fields_hash'}->{lc $_};      | 
| 
214
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         } else {  | 
| 
215
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
             SEARCH: for my $k (sort keys %{ $self->{'fields_hash'} }) {  | 
| 
 
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
216
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
                 if (lc( $k ) eq lc( $_ )) {  | 
| 
217
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
                     $index = $self->{'fields_hash'}->{$k};  | 
| 
218
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
                     last SEARCH;  | 
| 
219
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 }  | 
| 
220
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             }  | 
| 
221
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
222
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
         push @indexes, $index;  | 
| 
223
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
224
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
225
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
     $self->{'totals'} = $self->_total_chunk($self->{'rows'},\@indexes);  | 
| 
226
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
227
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
     return $self;  | 
| 
228
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
229
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
230
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub calc_subtotals {  | 
| 
231
 | 
  
0
  
 | 
 
 | 
 
 | 
  
0
  
 | 
  
1
  
 | 
0
 | 
     my ($self,$cols,$mask,$nodups) = @_;  | 
| 
232
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     return undef unless $self->{'rows'};  | 
| 
233
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
234
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     $self->{'subtotals_mask'} = $mask;  | 
| 
235
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     $cols = $self->_refinate($cols);  | 
| 
236
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
237
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     my @indexes;  | 
| 
238
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     for (@$cols) {  | 
| 
239
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         my $index;  | 
| 
240
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         if (exists $self->{'fields_hash'}->{$_}) {  | 
| 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
241
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
             $index = $self->{'fields_hash'}->{$_};      | 
| 
242
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         } elsif (exists $self->{'fields_hash'}->{lc $_}) {  | 
| 
243
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
             $index = $self->{'fields_hash'}->{lc $_};      | 
| 
244
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         } else {  | 
| 
245
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
             SEARCH: for my $k (sort keys %{ $self->{'fields_hash'} }) {  | 
| 
 
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
246
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
                 if (lc( $k ) eq lc( $_ )) {  | 
| 
247
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
                     $index = $self->{'fields_hash'}->{$k};  | 
| 
248
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
                     last SEARCH;  | 
| 
249
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 }  | 
| 
250
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             }  | 
| 
251
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
252
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         push @indexes, $index;  | 
| 
253
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
254
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
255
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     my $beg = 0;  | 
| 
256
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     foreach my $end (@{$self->{'body_breaks'}}) {  | 
| 
 
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
257
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         my $chunk = ([@{$self->{'rows'}}[$beg..$end]]);  | 
| 
 
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
258
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         push @{$self->{'sub_totals'}}, $self->_total_chunk($chunk,\@indexes);  | 
| 
 
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
259
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         $beg = $end + 1;  | 
| 
260
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
261
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
262
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     return $self;  | 
| 
263
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
264
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
265
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub set_row_colors {  | 
| 
266
 | 
  
0
  
 | 
 
 | 
 
 | 
  
0
  
 | 
  
1
  
 | 
0
 | 
     my ($self,$colors,$myattrib) = @_;  | 
| 
267
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
268
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     return $self unless ref $colors eq 'ARRAY';  | 
| 
269
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     return $self unless $#$colors >= 1;  | 
| 
270
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
271
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     my $ref = ($myattrib)  | 
| 
272
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
          ? { $myattrib => [@$colors] }  | 
| 
273
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
          : { style => {background => [@$colors]} }  | 
| 
274
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     ;  | 
| 
275
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
276
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     $self->modify(tr => $ref, 'body');  | 
| 
277
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
278
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # maybe that should be global?  | 
| 
279
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     #$self->modify(tr => $ref);  | 
| 
280
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
281
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     return $self;  | 
| 
282
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
283
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
284
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub set_col_colors {  | 
| 
285
 | 
  
0
  
 | 
 
 | 
 
 | 
  
0
  
 | 
  
1
  
 | 
0
 | 
     my ($self,$colors,$myattrib) = @_;  | 
| 
286
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
287
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     return $self unless ref $colors eq 'ARRAY';  | 
| 
288
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     return $self unless $#$colors >= 1;  | 
| 
289
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
290
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     my $cols = $self->_refinate();  | 
| 
291
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
292
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # trick #1: truncate colors to cols  | 
| 
293
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     $#$colors = $#$cols if $#$colors > $#$cols;  | 
| 
294
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
295
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # trick #2: keep adding colors  | 
| 
296
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     #unless ($#$cols % 2 and $#$colors % 2) {  | 
| 
297
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         my $temp = [@$colors];  | 
| 
298
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         push(@$colors,_rotate($temp)) until $#$colors == $#$cols;  | 
| 
299
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     #}  | 
| 
300
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
301
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     my $ref = ($myattrib)  | 
| 
302
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
          ? { $myattrib => [@$colors] }  | 
| 
303
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
          : { style => {background => [@$colors]} }  | 
| 
304
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     ;  | 
| 
305
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
306
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     $self->modify(td => $ref, $_) for @$cols;  | 
| 
307
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
308
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     return $self;  | 
| 
309
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
310
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
311
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub set_group {  | 
| 
312
 | 
1
 | 
 
 | 
 
 | 
  
1
  
 | 
  
1
  
 | 
2
 | 
     my ($self,$group,$nodup,$value) = @_;  | 
| 
313
 | 
1
 | 
  
 50
  
 | 
  
 33
  
 | 
 
 | 
 
 | 
7
 | 
     $self->{'nodup'} = $value || $self->{'null_value'} if $nodup;  | 
| 
314
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
315
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1
 | 
     my $index;  | 
| 
316
 | 
1
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
8
 | 
     if ($group =~ /^\d+$/) {  | 
| 
 
 | 
 
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
317
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         $index = $group;  | 
| 
318
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     } elsif (exists $self->{'fields_hash'}->{$group}) {  | 
| 
319
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
         $index = $self->{'fields_hash'}->{$group};      | 
| 
320
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
         $self->{'group'} = $group;  | 
| 
321
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     } elsif (exists $self->{'fields_hash'}->{lc $group}) {  | 
| 
322
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         $index = $self->{'fields_hash'}->{lc $group};      | 
| 
323
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         $self->{'group'} = lc $group;  | 
| 
324
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     } else {  | 
| 
325
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         SEARCH: for my $k (sort keys %{ $self->{'fields_hash'} }) {  | 
| 
 
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
326
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
             if (lc( $k ) eq lc( $group )) {  | 
| 
327
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
                 $index = $self->{'fields_hash'}->{$k};  | 
| 
328
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
                 $self->{'group'} = $k;  | 
| 
329
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
                 last SEARCH;  | 
| 
330
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             }  | 
| 
331
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
332
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
333
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
334
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # initialize the first 'repetition'  | 
| 
335
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
     my $rep = $self->{'rows'}->[0]->[$index];  | 
| 
336
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
337
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # loop through the whole rows array, storing  | 
| 
338
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # the points at which a new group starts  | 
| 
339
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
     for my $i (0..$self->get_row_count - 1) {  | 
| 
340
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
         my $new = $self->{'rows'}->[$i]->[$index];  | 
| 
341
 | 
2
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
4
 | 
         push @{$self->{'body_breaks'}}, $i - 1 unless ($rep eq $new);  | 
| 
 
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
342
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
         $rep = $new;  | 
| 
343
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
344
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
345
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
     push @{$self->{'body_breaks'}}, $self->get_row_count - 1;  | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
    | 
| 
346
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
347
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
     return $self;  | 
| 
348
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
349
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
350
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub set_pk {  | 
| 
351
 | 
  
0
  
 | 
 
 | 
 
 | 
  
0
  
 | 
  
1
  
 | 
0
 | 
     my $self = shift;  | 
| 
352
 | 
  
0
  
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
0
 | 
     my $pk   = shift || 'id';  | 
| 
353
 | 
  
0
  
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
0
 | 
     $pk = $pk =~ /^\d+$/ ? $self->_lookup_name($pk) || $pk : $pk;  | 
| 
354
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     carp "can't call set_pk(): too late to set primary key" if exists $self->{'rows'};  | 
| 
355
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     $self->{'pk'} = $pk;  | 
| 
356
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
357
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     return $self;  | 
| 
358
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
359
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
360
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub set_null_value {  | 
| 
361
 | 
  
0
  
 | 
 
 | 
 
 | 
  
0
  
 | 
  
1
  
 | 
0
 | 
     my ($self,$value) = @_;  | 
| 
362
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     $self->{'null_value'} = $value;  | 
| 
363
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     return $self;  | 
| 
364
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
365
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
366
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub get_col_count {  | 
| 
367
 | 
1
 | 
 
 | 
 
 | 
  
1
  
 | 
  
1
  
 | 
2
 | 
     my ($self) = @_;  | 
| 
368
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
     my $count = scalar @{$self->{'fields_arry'}};  | 
| 
 
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
    | 
| 
369
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
     return $count;  | 
| 
370
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
371
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
372
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub get_row_count {  | 
| 
373
 | 
6
 | 
 
 | 
 
 | 
  
6
  
 | 
  
1
  
 | 
7
 | 
     my ($self) = @_;  | 
| 
374
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
7
 | 
     my $count = scalar @{$self->{'rows'}};  | 
| 
 
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
12
 | 
    | 
| 
375
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
14
 | 
     return $count;  | 
| 
376
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
377
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
378
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub get_current_row {  | 
| 
379
 | 
  
0
  
 | 
 
 | 
 
 | 
  
0
  
 | 
  
1
  
 | 
0
 | 
     return shift->{'current_row'};  | 
| 
380
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
381
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
382
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub get_current_col {  | 
| 
383
 | 
  
0
  
 | 
 
 | 
 
 | 
  
0
  
 | 
  
1
  
 | 
0
 | 
     return shift->{'current_col'};  | 
| 
384
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
385
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
386
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub reset {  | 
| 
387
 | 
  
0
  
 | 
 
 | 
 
 | 
  
0
  
 | 
  
1
  
 | 
0
 | 
     my ($self) = @_;  | 
| 
388
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
389
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
390
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub add_cols {  | 
| 
391
 | 
  
0
  
 | 
 
 | 
 
 | 
  
0
  
 | 
  
1
  
 | 
0
 | 
     my ($self,$config) = @_;  | 
| 
392
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     $config = [$config] unless ref $config eq 'ARRAY';  | 
| 
393
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
394
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     foreach (@$config) {  | 
| 
395
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         next unless ref $_ eq 'HASH';  | 
| 
396
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         my ($name,$data,$pos) = @$_{(qw(name data before))};  | 
| 
397
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         my $max_pos = $self->get_col_count();  | 
| 
398
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
399
 | 
  
0
  
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
0
 | 
         $pos  = $self->_lookup_index(ucfirst $pos || '') || $max_pos unless defined $pos && $pos =~ /^\d+$/;  | 
| 
 
 | 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
400
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         $pos  = $max_pos if $pos > $max_pos;  | 
| 
401
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         $data = [$data] unless ref $data eq 'ARRAY';  | 
| 
402
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
403
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         splice(@{$self->{'fields_arry'}},$pos,0,$name);  | 
| 
 
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
404
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         $self->_reset_fields_hash();  | 
| 
405
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         splice(@$_,$pos,0,_rotate($data)) for (@{$self->{rows}});  | 
| 
 
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
406
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
407
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
408
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     return $self;  | 
| 
409
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
410
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
411
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub drop_cols {  | 
| 
412
 | 
  
0
  
 | 
 
 | 
 
 | 
  
0
  
 | 
  
1
  
 | 
0
 | 
     my ($self,$cols) = @_;  | 
| 
413
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     $cols = $self->_refinate($cols);  | 
| 
414
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
415
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     foreach my $col (@$cols) {  | 
| 
416
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         my $index = delete $self->{'fields_hash'}->{$col};  | 
| 
417
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         splice(@{$self->{'fields_arry'}},$index,1);  | 
| 
 
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
418
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         $self->_reset_fields_hash();  | 
| 
419
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         splice(@$_,$index,1) for (@{$self->{'rows'}});  | 
| 
 
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
420
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
421
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
422
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     return $self;  | 
| 
423
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
424
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
425
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 ###################### DEPRECATED ##################################  | 
| 
426
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
427
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub get_table {   | 
| 
428
 | 
  
0
  
 | 
 
 | 
 
 | 
  
0
  
 | 
  
1
  
 | 
0
 | 
     carp "get_table() is deprecated. Use output() instead";  | 
| 
429
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     output(@_);  | 
| 
430
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
431
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
432
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub modify_tag {  | 
| 
433
 | 
  
0
  
 | 
 
 | 
 
 | 
  
0
  
 | 
  
1
  
 | 
0
 | 
     carp "modify_tag() is deprecated. Use modify() instead";  | 
| 
434
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     modify(@_);  | 
| 
435
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
436
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
437
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub map_col {   | 
| 
438
 | 
  
0
  
 | 
 
 | 
 
 | 
  
0
  
 | 
  
1
  
 | 
0
 | 
     carp "map_col() is deprecated. Use map_cell() instead";  | 
| 
439
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     map_cell(@_);  | 
| 
440
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
441
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
442
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #################### UNDER THE HOOD ################################  | 
| 
443
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
444
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # repeat: it only looks complicated  | 
| 
445
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
446
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _build_table {  | 
| 
447
 | 
7
 | 
 
 | 
 
 | 
  
7
  
 | 
 
 | 
10
 | 
     my ($self)  = @_;  | 
| 
448
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
12
 | 
     my $attribs = $self->{'global'}->{'table'};  | 
| 
449
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
450
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
7
 | 
     my ($head,$body,$foot);  | 
| 
451
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
16
 | 
     $head = $self->_build_head;  | 
| 
452
 | 
7
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
38
 | 
     $body = $self->{'rows'}   ?  $self->_build_body : '';  | 
| 
453
 | 
7
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
18
 | 
     $foot = $self->{'totals'} ?  $self->_build_foot : '';  | 
| 
454
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
455
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # w3c says tfoot comes before tbody ...  | 
| 
456
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
14
 | 
     my $cdata = $head . $foot . $body;  | 
| 
457
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
458
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
18
 | 
     return _tag_it('table', $attribs, $cdata) . $N;  | 
| 
459
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
460
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
461
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _build_head {  | 
| 
462
 | 
7
 | 
 
 | 
 
 | 
  
7
  
 | 
 
 | 
10
 | 
     my ($self) = @_;  | 
| 
463
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6
 | 
     my ($attribs,$cdata,$caption);  | 
| 
464
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
9
 | 
     my $output = '';  | 
| 
465
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
466
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # build the  tag if applicable  | 
| 
467
 | 
7
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
19
 | 
     if ($caption = $self->{'global'}->{'caption'}) {  | 
| 
468
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         $attribs = $self->{'global'}->{'caption_attribs'};  | 
| 
469
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         $cdata   = $self->{'encode_cells'} ? $self->_xml_encode($caption) : $caption;  | 
| 
470
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         $output .= $N.$T . _tag_it('caption', $attribs, $cdata);  | 
| 
471
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
472
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
473
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # build the  tags if applicable  | 
| 
474
 | 
7
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
15
 | 
     if ($attribs = $self->{'global'}->{'colgroup'}) {  | 
| 
475
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         $cdata   = $self->_build_head_colgroups();  | 
| 
476
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         $output .= $N.$T . _tag_it('colgroup', $attribs, $cdata);  | 
| 
477
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
478
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
479
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # go ahead and stop if they don't want the head  | 
| 
480
 | 
7
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
18
 | 
     return "$output\n" if $self->{'no_head'};  | 
| 
481
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
482
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # prepare  | 
 tag info 
| 
483
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $tr_attribs = _merge_attribs(  | 
| 
484
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
30
 | 
         $self->{'head'}->{'tr'}, $self->{'global'}->{'tr'}  | 
| 
485
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     );  | 
| 
486
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
24
 | 
     my $tr_cdata   = $self->_build_head_row();  | 
| 
487
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
488
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # prepare the  tag info 
| 
489
 | 
7
 | 
 
 | 
  
 33
  
 | 
 
 | 
 
 | 
34
 | 
     $attribs = $self->{'head'}->{'thead'} || $self->{'global'}->{'thead'};  | 
 
| 
490
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
23
 | 
     $cdata   = $N.$T . _tag_it('tr', $tr_attribs, $tr_cdata) . $N.$T;  | 
 
| 
491
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
 
| 
492
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # add the  tag to the output 
| 
493
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
16
 | 
     $output .= $N.$T . _tag_it('thead', $attribs, $cdata) . $N;  | 
 
| 
494
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
 
| 
495
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
 
| 
496
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _build_head_colgroups {  | 
 
| 
497
 | 
  
0
  
 | 
 
 | 
 
 | 
  
0
  
 | 
 
 | 
0
 | 
     my ($self) = @_;  | 
 
| 
498
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     my (@cols,$output);  | 
 
| 
499
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
 
| 
500
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     return unless $self->{'colgroups'};  | 
 
| 
501
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     return undef unless @cols = @{$self->{'colgroups'}};  | 
 
| 
 
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
 
| 
502
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
 
| 
503
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     foreach (@cols) {  | 
 
| 
504
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         $output .= $N.$T.$T . _tag_it('col', $_);  | 
 
| 
505
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
 
| 
506
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     $output .= $N.$T;  | 
 
| 
507
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
 
| 
508
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     return $output;  | 
 
| 
509
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
 
| 
510
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
 
| 
511
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _build_head_row {  | 
 
| 
512
 | 
7
 | 
 
 | 
 
 | 
  
7
  
 | 
 
 | 
9
 | 
     my ($self) = @_;  | 
 
| 
513
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
9
 | 
     my $output = $N;  | 
 
| 
514
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
8
 | 
     my @copy   = @{$self->{'fields_arry'}};  | 
 
| 
 
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
23
 | 
    | 
 
| 
515
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
 
| 
516
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
14
 | 
     foreach my $field (@copy) {  | 
 
| 
517
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         my $attribs = _merge_attribs(  | 
 
| 
518
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             $self->{$field}->{'th'}   || $self->{'head'}->{'th'},  | 
 
| 
519
 | 
14
 | 
 
 | 
  
 33
  
 | 
 
 | 
 
 | 
68
 | 
             $self->{'global'}->{'th'} || $self->{'head'}->{'th'},  | 
 
| 
 
 | 
 
 | 
 
 | 
  
 33
  
 | 
 
 | 
 
 | 
 
 | 
    | 
 
| 
520
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         );  | 
 
| 
521
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
 
| 
522
 | 
14
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
40
 | 
         if (my $sub = $self->{'map_head'}->{$field}) {  | 
 
| 
 
 | 
 
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
 
| 
523
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
7
 | 
             $field = $sub->($field);  | 
 
| 
524
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
 
| 
525
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         elsif (!$self->{'no_ucfirst'}) {  | 
 
| 
526
 | 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
23
 | 
             $field = ucfirst( lc( $field ) );  | 
 
| 
527
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
 
| 
528
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
 
| 
529
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         # bug 21761 "Special XML characters should be expressed as entities"  | 
 
| 
530
 | 
14
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
74
 | 
         $field = $self->_xml_encode( $field ) if $self->{'encode_cells'};  | 
 
| 
531
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
 
| 
532
 | 
14
 | 
 
 | 
 
 | 
 
 | 
 
 | 
30
 | 
         $output .= $T.$T . _tag_it('th', $attribs, $field) . $N;  | 
 
| 
533
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
 
| 
534
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
 
| 
535
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
21
 | 
     return $output . $T;  | 
 
| 
536
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
 
| 
537
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
 
| 
538
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _build_body {  | 
 
| 
539
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
 
| 
540
 | 
7
 | 
 
 | 
 
 | 
  
7
  
 | 
 
 | 
10
 | 
     my ($self)   = @_;  | 
 
| 
541
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
7
 | 
     my $beg      = 0;  | 
 
| 
542
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
8
 | 
     my $output;  | 
 
| 
543
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
 
| 
544
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # if a group was not set via set_group(), then use the entire 2-d array  | 
 
| 
545
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my @indicies = exists $self->{'body_breaks'}  | 
 
| 
546
 | 
7
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
20
 | 
         ? @{$self->{'body_breaks'}}  | 
 
| 
 
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6
 | 
    | 
 
| 
547
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         : ($self->get_row_count - 1);  | 
 
| 
548
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
 
| 
549
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # the skinny here is to grab a slice of the rows, one for each group  | 
 
| 
550
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
12
 | 
     foreach my $end (@indicies) {  | 
 
| 
551
 | 
7
 | 
 
 | 
  
 50
  
 | 
 
 | 
 
 | 
14
 | 
         my $body_group = $self->_build_body_group([@{$self->{'rows'}}[$beg..$end]]) || '';  | 
 
| 
552
 | 
7
 | 
 
 | 
  
 33
  
 | 
 
 | 
 
 | 
28
 | 
         my $attribs    = $self->{'global'}->{'tbody'} || $self->{'body'}->{'tbody'};  | 
 
| 
553
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
13
 | 
         my $cdata      = $N . $body_group . $T;  | 
 
| 
554
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
 
| 
555
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
14
 | 
         $output .= $T . _tag_it('tbody',$attribs,$cdata) . $N;  | 
 
| 
556
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
15
 | 
         $beg = $end + 1;  | 
 
| 
557
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
 
| 
558
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
16
 | 
     return $output;  | 
 
| 
559
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
 
| 
560
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
 
| 
561
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _build_body_group {  | 
 
| 
562
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
 
| 
563
 | 
7
 | 
 
 | 
 
 | 
  
7
  
 | 
 
 | 
9
 | 
     my ($self,$chunk) = @_;  | 
 
| 
564
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6
 | 
     my ($output,$cdata);  | 
 
| 
565
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $attribs = _merge_attribs(  | 
 
| 
566
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
23
 | 
         $self->{'body'}->{'tr'}, $self->{'global'}->{'tr'}  | 
 
| 
567
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     );  | 
 
| 
568
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
14
 | 
     my $pk_col = '';  | 
 
| 
569
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
 
| 
570
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # build the rows  | 
 
| 
571
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
22
 | 
     for my $i (0..$#$chunk) {  | 
 
| 
572
 | 
14
 | 
 
 | 
 
 | 
 
 | 
 
 | 
13
 | 
         my @row  = @{$chunk->[$i]};  | 
 
| 
 
 | 
14
 | 
 
 | 
 
 | 
 
 | 
 
 | 
30
 | 
    | 
 
| 
573
 | 
14
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
34
 | 
         $pk_col  = splice(@row,$self->{'pk_index'},1) if defined $self->{'pk_index'};  | 
 
| 
574
 | 
14
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
81
 | 
         $cdata   = $self->_build_body_row(\@row, ($i and $self->{'nodup'} or 0), $pk_col);  | 
 
| 
575
 | 
14
 | 
 
 | 
 
 | 
 
 | 
 
 | 
57
 | 
         $output .= $T . _tag_it('tr',$attribs,$cdata) . $N;  | 
 
| 
576
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
 
| 
577
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
 
| 
578
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # build the subtotal row if applicable  | 
 
| 
579
 | 
7
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
9
 | 
     if (my $subtotals = shift @{$self->{'sub_totals'}}) {  | 
 
| 
 
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
26
 | 
    | 
 
| 
580
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         $cdata   = $self->_build_body_subtotal($subtotals);  | 
 
| 
581
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         $output .= $T . _tag_it('tr',$attribs,$cdata) . $N;  | 
 
| 
582
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
 
| 
583
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
 
| 
584
 | 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
21
 | 
     return $output;  | 
 
| 
585
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
 
| 
586
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
 
| 
587
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _build_body_row {  | 
 
| 
588
 | 
14
 | 
 
 | 
 
 | 
  
14
  
 | 
 
 | 
21
 | 
     my ($self,$row,$nodup,$pk) = @_;  | 
 
| 
589
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
 
| 
590
 | 
14
 | 
 
 | 
 
 | 
 
 | 
 
 | 
13
 | 
     my $group  = $self->{'group'};  | 
 
| 
591
 | 
14
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
35
 | 
     my $index  = $self->_lookup_index($group) if $group;  | 
 
| 
592
 | 
14
 | 
 
 | 
 
 | 
 
 | 
 
 | 
18
 | 
     my $output = $N;  | 
 
| 
593
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
 
| 
594
 | 
14
 | 
 
 | 
 
 | 
 
 | 
 
 | 
23
 | 
     $self->{'current_row'} = $pk;  | 
 
| 
595
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
 
| 
596
 | 
14
 | 
 
 | 
 
 | 
 
 | 
 
 | 
27
 | 
     for (0..$#$row) {  | 
 
| 
597
 | 
28
 | 
 
 | 
 
 | 
 
 | 
 
 | 
49
 | 
         my $name    = $self->_lookup_name($_);  | 
 
| 
598
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         my $attribs = _merge_attribs(  | 
 
| 
599
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             $self->{$name}->{'td'}    || $self->{'body'}->{'td'},   | 
 
| 
600
 | 
28
 | 
 
 | 
  
 33
  
 | 
 
 | 
 
 | 
129
 | 
             $self->{'global'}->{'td'} || $self->{'body'}->{'td'},  | 
 
| 
 
 | 
 
 | 
 
 | 
  
 33
  
 | 
 
 | 
 
 | 
 
 | 
    | 
 
| 
601
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         );  | 
 
| 
602
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
 
| 
603
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         # suppress warnings AND keep 0 from becoming    | 
 
| 
604
 | 
28
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
84
 | 
         $row->[$_] = '' unless defined($row->[$_]);  | 
 
| 
605
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
 
| 
606
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         # bug 21761 "Special XML characters should be expressed as entities"  | 
 
| 
607
 | 
28
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
55
 | 
         $row->[$_] = $self->_xml_encode( $row->[$_] ) if $self->{'encode_cells'};  | 
 
| 
608
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
 
| 
609
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         my $cdata = ($row->[$_] =~ /^\s+$/)   | 
 
| 
610
 | 
28
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
89
 | 
             ? $self->{'null_value'}  | 
 
| 
611
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             : $row->[$_]   | 
 
| 
612
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         ;  | 
 
| 
613
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
 
| 
614
 | 
28
 | 
 
 | 
 
 | 
 
 | 
 
 | 
47
 | 
         $self->{'current_col'} = $name;  | 
 
| 
615
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
 
| 
616
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         $cdata = ($nodup and $index == $_)  | 
 
| 
617
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             ? $self->{'nodup'}  | 
 
| 
618
 | 
28
 | 
  
100
  
 | 
  
100
  
 | 
 
 | 
 
 | 
110
 | 
             : _map_it($self->{'map_cell'}->{$name},$cdata)  | 
 
| 
619
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         ;  | 
 
| 
620
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
 
| 
621
 | 
28
 | 
 
 | 
 
 | 
 
 | 
 
 | 
60
 | 
         $output .= $T.$T . _tag_it('td', $attribs, $cdata) . $N;  | 
 
| 
622
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
 
| 
623
 | 
14
 | 
 
 | 
 
 | 
 
 | 
 
 | 
39
 | 
     return $output . $T;  | 
 
| 
624
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
 
| 
625
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
 
| 
626
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _build_body_subtotal {  | 
 
| 
627
 | 
  
0
  
 | 
 
 | 
 
 | 
  
0
  
 | 
 
 | 
0
 | 
     my ($self,$row) = @_;  | 
 
| 
628
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     my $output = $N;  | 
 
| 
629
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
 
| 
630
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     return '' unless $row;  | 
 
| 
631
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
 
| 
632
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     for (0..$#$row) {  | 
 
| 
633
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         my $name    = $self->_lookup_name($_);  | 
 
| 
634
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         my $sum     = ($row->[$_]);  | 
 
| 
635
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         my $attribs = _merge_attribs(  | 
 
| 
636
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             $self->{$name}->{'th'}    || $self->{'body'}->{'th'},  | 
 
| 
637
 | 
  
0
  
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
0
 | 
             $self->{'global'}->{'th'} || $self->{'body'}->{'th'},  | 
 
| 
 
 | 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
    | 
 
| 
638
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         );  | 
 
| 
639
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
 
| 
640
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         # use sprintf if mask was supplied  | 
 
| 
641
 | 
  
0
  
 | 
  
  0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
0
 | 
         if ($self->{'subtotals_mask'} and defined $sum) {  | 
 
| 
642
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
             $sum = sprintf($self->{'subtotals_mask'},$sum);  | 
 
| 
643
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
 
| 
644
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         else {  | 
 
| 
645
 | 
  
0
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
             $sum = (defined $sum) ? $sum : $self->{'null_value'};  | 
 
| 
646
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
 
| 
647
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
 
| 
648
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         $output .= $T.$T . _tag_it('th', $attribs, $sum) . $N;  | 
 
| 
649
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
 
| 
650
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     return $output . $T;  | 
 
| 
651
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
 
| 
652
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
 
| 
653
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _build_foot {  | 
 
| 
654
 | 
2
 | 
 
 | 
 
 | 
  
2
  
 | 
 
 | 
8
 | 
     my ($self) = @_;  | 
 
| 
655
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
 
| 
656
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     my $tr_attribs = _merge_attribs(  | 
 
| 
657
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         # notice that foot is 1st and global 2nd - different than rest  | 
 
| 
658
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6
 | 
         $self->{'foot'}->{'tr'}, $self->{'global'}->{'tr'}  | 
 
| 
659
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     );  | 
 
| 
660
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6
 | 
     my $tr_cdata   = $self->_build_foot_row();  | 
 
| 
661
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
 
| 
662
 | 
2
 | 
 
 | 
  
 33
  
 | 
 
 | 
 
 | 
6
 | 
     my $attribs = $self->{'foot'}->{'tfoot'} || $self->{'global'}->{'tfoot'};  | 
 
| 
663
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
     my $cdata   = $N.$T . _tag_it('tr', $tr_attribs, $tr_cdata) . $N.$T;  | 
 
| 
664
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
 
| 
665
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
     return $T . _tag_it('tfoot',$attribs,$cdata) . $N;  | 
 
| 
666
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
 
| 
667
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
 
| 
668
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _build_foot_row {  | 
 
| 
669
 | 
2
 | 
 
 | 
 
 | 
  
2
  
 | 
 
 | 
2
 | 
     my ($self) = @_;  | 
 
| 
670
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
 
| 
671
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
     my $output = $N;  | 
 
| 
672
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
     my $row    = $self->{'totals'};  | 
 
| 
673
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
 
| 
674
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
     for (0..$#$row) {  | 
 
| 
675
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6
 | 
         my $name    = $self->_lookup_name($_);  | 
 
| 
676
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         my $attribs = _merge_attribs(  | 
 
| 
677
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             $self->{$name}->{'th'}    || $self->{'foot'}->{'th'},  | 
 
| 
678
 | 
4
 | 
 
 | 
  
 33
  
 | 
 
 | 
 
 | 
18
 | 
             $self->{'global'}->{'th'} || $self->{'foot'}->{'th'},  | 
 
| 
 
 | 
 
 | 
 
 | 
  
 33
  
 | 
 
 | 
 
 | 
 
 | 
    | 
 
| 
679
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         );  | 
 
| 
680
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5
 | 
         my $sum     = ($row->[$_]);  | 
 
| 
681
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
 
| 
682
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         # use sprintf if mask was supplied  | 
 
| 
683
 | 
4
 | 
  
 50
  
 | 
  
 33
  
 | 
 
 | 
 
 | 
12
 | 
         if ($self->{'totals_mask'} and defined $sum) {  | 
 
| 
684
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
             $sum = sprintf($self->{'totals_mask'},$sum)  | 
 
| 
685
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
 
| 
686
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         else {  | 
 
| 
687
 | 
4
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
8
 | 
             $sum = defined $sum ? $sum : $self->{'null_value'};  | 
 
| 
688
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
 
| 
689
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
 
| 
690
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
9
 | 
         $output .= $T.$T . _tag_it('th', $attribs, $sum) . $N;  | 
 
| 
691
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
 
| 
692
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
     return $output . $T;  | 
 
| 
693
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
 
| 
694
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
 
| 
695
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # builds a tag and it's enclosed data  | 
 
| 
696
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _tag_it {  | 
 
| 
697
 | 
92
 | 
 
 | 
 
 | 
  
92
  
 | 
 
 | 
106
 | 
     my ($name,$attribs,$cdata) = @_;  | 
 
| 
698
 | 
92
 | 
 
 | 
 
 | 
 
 | 
 
 | 
108
 | 
     my $text = "<\L$name\E";  | 
 
| 
699
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
 
| 
700
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # build the attributes if any - skip blank vals  | 
 
| 
701
 | 
92
 | 
 
 | 
 
 | 
 
 | 
 
 | 
77
 | 
     for my $k (sort keys %{$attribs}) {  | 
 
| 
 
 | 
92
 | 
 
 | 
 
 | 
 
 | 
 
 | 
207
 | 
    | 
 
| 
702
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5
 | 
         my $v = $attribs->{$k};  | 
 
| 
703
 | 
4
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
9
 | 
         if (ref $v eq 'HASH') {  | 
 
| 
704
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             $v = join('; ', map {   | 
 
| 
705
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6
 | 
                 my $attrib = $_;  | 
 
| 
 
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
    | 
 
| 
706
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 my $value  = (ref $v->{$_} eq 'ARRAY')   | 
 
| 
707
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                     ? _rotate($v->{$_})   | 
 
| 
708
 | 
4
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
10
 | 
                     : $v->{$_};  | 
 
| 
709
 | 
4
 | 
 
 | 
  
 50
  
 | 
 
 | 
 
 | 
19
 | 
                 join(': ',$attrib,$value||'');  | 
 
| 
710
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             } sort keys %$v) . ';';  | 
 
| 
711
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
 
| 
712
 | 
4
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
7
 | 
         $v = _rotate($v) if (ref $v eq 'ARRAY');  | 
 
| 
713
 | 
4
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
18
 | 
         $text .= qq| \L$k\E="$v"| unless $v =~ /^$/;  | 
 
| 
714
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
 
| 
715
 | 
92
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
457
 | 
     $text .= (defined $cdata) ? ">$cdata\L$name\E>" : '/>';  | 
 
| 
716
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
 
| 
717
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
 
| 
718
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # used by map_cell() and map_head()  | 
 
| 
719
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _map_it {  | 
 
| 
720
 | 
25
 | 
 
 | 
 
 | 
  
25
  
 | 
 
 | 
35
 | 
     my ($sub,$datum) = @_;  | 
 
| 
721
 | 
25
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
57
 | 
     return $datum unless $sub;  | 
 
| 
722
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     return $datum = $sub->($datum);  | 
 
| 
723
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
 
| 
724
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
 
| 
725
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # used by calc_totals() and calc_subtotals()  | 
 
| 
726
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _total_chunk {  | 
 
| 
727
 | 
1
 | 
 
 | 
 
 | 
  
1
  
 | 
 
 | 
1
 | 
     my ($self,$chunk,$indexes) = @_;  | 
 
| 
728
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
     my %totals;  | 
 
| 
729
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
 
| 
730
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
     foreach my $row (@$chunk) {  | 
 
| 
731
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
         foreach (@$indexes) {  | 
 
| 
732
 | 
2
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
11
 | 
             $totals{$_} += $row->[$_] if $row->[$_] =~ /^[-0-9\.]+$/;  | 
 
| 
733
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }      | 
 
| 
734
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
 
| 
735
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
 
| 
736
 | 
1
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
24
 | 
     return [ map { defined $totals{$_} ? $totals{$_} : undef } (0 .. $self->get_col_count() - 1) ];  | 
 
| 
 
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
8
 | 
    | 
 
| 
737
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
 
| 
738
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
 
| 
739
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # uses %ESCAPES to convert the '4 Horsemen' of XML  | 
 
| 
740
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # big thanks to Matt Sergeant   | 
 
| 
741
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _xml_encode {  | 
 
| 
742
 | 
6
 | 
 
 | 
 
 | 
  
6
  
 | 
 
 | 
13
 | 
     my ($self,$str) = @_;  | 
 
| 
743
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
27
 | 
     $str =~ s/([&<>"])/$ESCAPES{$1}/ge;  | 
 
| 
 
 | 
24
 | 
 
 | 
 
 | 
 
 | 
 
 | 
87
 | 
    | 
 
| 
744
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
17
 | 
     return $str;  | 
 
| 
745
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
 
| 
746
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
 
| 
747
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # returns value of and moves first element to last  | 
 
| 
748
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _rotate {  | 
 
| 
749
 | 
4
 | 
 
 | 
 
 | 
  
4
  
 | 
 
 | 
4
 | 
     my $ref  = shift;  | 
 
| 
750
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
299
 | 
     my $next = shift @$ref;  | 
 
| 
751
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
15
 | 
     push @$ref, $next;  | 
 
| 
752
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6
 | 
     return $next;  | 
 
| 
753
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
 
| 
754
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
 
| 
755
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # always returns an array ref  | 
 
| 
756
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _refinate {  | 
 
| 
757
 | 
3
 | 
 
 | 
 
 | 
  
3
  
 | 
 
 | 
3
 | 
     my ($self,$ref) = @_;  | 
 
| 
758
 | 
3
 | 
  
 50
  
 | 
  
 33
  
 | 
 
 | 
 
 | 
8
 | 
     $ref = undef if ref($ref) eq 'ARRAY' && scalar( @$ref ) < 1;  | 
 
| 
759
 | 
3
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
10
 | 
     $ref = [@{$self->{'fields_arry'}}] unless defined $ref;  | 
 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
 
| 
760
 | 
3
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
9
 | 
     $ref = [$ref] unless ref $ref eq 'ARRAY';  | 
 
| 
761
 | 
3
 | 
  
 50
  
 | 
  
  0
  
 | 
 
 | 
 
 | 
4
 | 
     return [map {$_ =~ /^\d+$/ ? $self->_lookup_name($_) || $_ : $_} @$ref];  | 
 
| 
 
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
17
 | 
    | 
 
| 
762
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
 
| 
763
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
 
| 
764
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _merge_attribs {  | 
 
| 
765
 | 
62
 | 
 
 | 
 
 | 
  
62
  
 | 
 
 | 
73
 | 
     my ($hash1,$hash2) = @_;  | 
 
| 
766
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
 
| 
767
 | 
62
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
169
 | 
     return $hash1 unless $hash2;  | 
 
| 
768
 | 
4
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
6
 | 
     return $hash2 unless $hash1;  | 
 
| 
769
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
 
| 
770
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
11
 | 
     return {%$hash2,%$hash1};  | 
 
| 
771
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
 
| 
772
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
 
| 
773
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _lookup_name {  | 
 
| 
774
 | 
32
 | 
 
 | 
 
 | 
  
32
  
 | 
 
 | 
35
 | 
     my ($self,$index) = @_;  | 
 
| 
775
 | 
32
 | 
 
 | 
 
 | 
 
 | 
 
 | 
50
 | 
     return $self->{'fields_arry'}->[$index];  | 
 
| 
776
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
 
| 
777
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
 
| 
778
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _lookup_index {  | 
 
| 
779
 | 
6
 | 
 
 | 
 
 | 
  
6
  
 | 
 
 | 
4
 | 
     my ($self,$name) = @_;  | 
 
| 
780
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
19
 | 
     return $self->{'fields_hash'}->{$name};  | 
 
| 
781
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
 
| 
782
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
 
| 
783
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _reset_fields_hash {  | 
 
| 
784
 | 
2
 | 
 
 | 
 
 | 
  
2
  
 | 
 
 | 
3
 | 
     my $self = shift;  | 
 
| 
785
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5
 | 
     my $i    = 0;  | 
 
| 
786
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
     $self->{fields_hash} = { map { $_ => $i++ } @{$self->{fields_arry}} };  | 
 
| 
 
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
21
 | 
    | 
 
| 
 
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6
 | 
    | 
 
| 
787
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
 
| 
788
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
 
| 
789
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # assigns a non-DBI supplied data table (2D array ref)  | 
 
| 
790
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _do_black_magic {  | 
 
| 
791
 | 
2
 | 
 
 | 
 
 | 
  
2
  
 | 
 
 | 
5
 | 
     my ($self,$ref,$headers) = @_;  | 
 
| 
792
 | 
2
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
11
 | 
     croak "bad data" unless ref( $ref->[0] ) eq 'ARRAY';  | 
 
| 
793
 | 
2
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
7
 | 
     $self->{'fields_arry'} = $headers ? [@$headers] : [ @{ shift @$ref } ];  | 
 
| 
 
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
16
 | 
    | 
 
| 
794
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
10
 | 
     $self->{'fields_hash'} = $self->_reset_fields_hash();  | 
 
| 
795
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
8
 | 
     $self->{'rows'}        = $ref;  | 
 
| 
796
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
 
| 
797
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
 
| 
798
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # disconnect database handle if i created it  | 
 
| 
799
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub DESTROY {  | 
 
| 
800
 | 
2
 | 
 
 | 
 
 | 
  
2
  
 | 
 
 | 
931
 | 
     my ($self) = @_;  | 
 
| 
801
 | 
2
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
10
 | 
     unless ($self->{'keep_alive'}) {  | 
 
| 
802
 | 
2
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
87
 | 
         $self->{'dbh'}->disconnect if defined $self->{'dbh'};  | 
 
| 
803
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
 
| 
804
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
 
| 
805
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
 
| 
806
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 1;  | 
 
| 
807
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 __END__  | 
 
 |   |