line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package RTF::Control; |
2
|
|
|
|
|
|
|
$RTF::Control::VERSION = '1.12'; |
3
|
8
|
|
|
8
|
|
2340
|
use strict; |
|
8
|
|
|
|
|
15
|
|
|
8
|
|
|
|
|
248
|
|
4
|
8
|
|
|
8
|
|
39
|
use warnings; |
|
8
|
|
|
|
|
15
|
|
|
8
|
|
|
|
|
387
|
|
5
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
# Sonovision-Itep, Philippe Verdret 1998-1999 |
7
|
|
|
|
|
|
|
# TPF - Pete Sergeant 2003 - 2004 |
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
=head1 NAME |
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
RTF::Control - Application of RTF::Parser for document conversion |
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
=head1 VERSION |
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
version 1.12 |
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
=head1 DESCRIPTION |
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
Application of RTF::Parser for document conversion |
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
=head1 OVERVIEW |
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
L is a sublass of L. L can be seen as |
24
|
|
|
|
|
|
|
a helper module for people wanting to write their own document convertors - |
25
|
|
|
|
|
|
|
L and L both subclass it. |
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
I am the new maintainer of this module. My aim is to keep the interface |
28
|
|
|
|
|
|
|
identical to the old interface while cleaning up, documenting, and testing |
29
|
|
|
|
|
|
|
the internals. There are things in the interface I'm unhappy with, and things |
30
|
|
|
|
|
|
|
I like - however, I'm maintaining rather than developing the module, so, the |
31
|
|
|
|
|
|
|
interface is mostly frozen. |
32
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
=head1 HOW IT ALL WORKS |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
For starters, go and look at the source of M |
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
Except for B, the following is a list of variables |
39
|
|
|
|
|
|
|
exported by RTF::Control that you're expected to tinker with in your |
40
|
|
|
|
|
|
|
own subclass. |
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
=head2 RTF::Parser subs |
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
If you read the docs of RTF::Parser you'll see that you can redefine some |
45
|
|
|
|
|
|
|
subs there - RTF::Control has its own definitions for all of these, but you |
46
|
|
|
|
|
|
|
might want to over-ride C, C, and C. We'll look |
47
|
|
|
|
|
|
|
at what the defaults of each of these do, and what you need to do if you |
48
|
|
|
|
|
|
|
want to override any of them a little further down. |
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
=head2 %symbol |
51
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
This hash is actually merged into %do_on_control, with the value wrapped in |
53
|
|
|
|
|
|
|
a subroutine that effectively says C. You can put any control |
54
|
|
|
|
|
|
|
words that should map directly to a certain output in here - C<\tab>, for |
55
|
|
|
|
|
|
|
example could be C<$symbol{'tab'} = "\t">. |
56
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
=head2 %info |
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
This hash gets filled with document meta-data, as per the RTF specification. |
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
=head2 %par_props |
62
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
Not really sure, but paragraph properties |
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
=head2 %do_on_event %do_on_control |
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
%do_on_control tells us what to do when we meet a specific control word. |
68
|
|
|
|
|
|
|
The values are coderefs. %do_on_event also holds coderefs, but these are |
69
|
|
|
|
|
|
|
more abstract things to do, say when the stylesheet changes. %do_on_event |
70
|
|
|
|
|
|
|
thingies tend to be called by %do_on_control thingies, as far as I can tell. |
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
=head2 $style $newstyle |
73
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
Style is the current style, $newstyle is the one we're about to |
75
|
|
|
|
|
|
|
change to if we're about to change... |
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
=head2 $event |
78
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
Current event |
80
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
=head2 $text |
82
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
Pending text |
84
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
=cut |
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
# Define all our dependencies and other fluff |
88
|
|
|
|
|
|
|
|
89
|
8
|
|
|
8
|
|
4879
|
use RTF::Parser; |
|
8
|
|
|
|
|
21
|
|
|
8
|
|
|
|
|
330
|
|
90
|
8
|
|
|
8
|
|
47
|
use RTF::Config; |
|
8
|
|
|
|
|
15
|
|
|
8
|
|
|
|
|
657
|
|
91
|
8
|
|
|
8
|
|
4600
|
use RTF::Charsets; # define names of chars |
|
8
|
|
|
|
|
21
|
|
|
8
|
|
|
|
|
1006
|
|
92
|
|
|
|
|
|
|
|
93
|
8
|
|
|
8
|
|
48
|
use File::Basename; |
|
8
|
|
|
|
|
14
|
|
|
8
|
|
|
|
|
916
|
|
94
|
8
|
|
|
8
|
|
41
|
use Exporter; |
|
8
|
|
|
|
|
13
|
|
|
8
|
|
|
|
|
509
|
|
95
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
# I'm an RTF::Parser! I'm an Exporter! I'm a class! |
97
|
|
|
|
|
|
|
# "When I grow up, I'm going to bovine university!" |
98
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
@RTF::Control::ISA = qw(Exporter RTF::Parser); |
100
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
# Define the symbols we'll be exporting - these are |
102
|
|
|
|
|
|
|
# documented in the API part of the POD and a little |
103
|
|
|
|
|
|
|
# further down |
104
|
|
|
|
|
|
|
|
105
|
8
|
|
|
|
|
927
|
use vars qw( |
106
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
%symbol %info %par_props %do_on_event %do_on_control |
108
|
|
|
|
|
|
|
$style $newstyle $event $text |
109
|
|
|
|
|
|
|
|
110
|
8
|
|
|
8
|
|
41
|
); |
|
8
|
|
|
|
|
10
|
|
111
|
|
|
|
|
|
|
|
112
|
|
|
|
|
|
|
# There are used to that we have named arguments for callbacks |
113
|
|
|
|
|
|
|
# I don't like this, but hey, I didn't design it, and I'm meant |
114
|
|
|
|
|
|
|
# to be maintaining the interface :-) |
115
|
|
|
|
|
|
|
|
116
|
8
|
|
|
8
|
|
66
|
use constant SELF => 0; # rtf processor instance |
|
8
|
|
|
|
|
14
|
|
|
8
|
|
|
|
|
510
|
|
117
|
8
|
|
|
8
|
|
34
|
use constant CONTROL => 1; # control word |
|
8
|
|
|
|
|
16
|
|
|
8
|
|
|
|
|
3371
|
|
118
|
8
|
|
|
8
|
|
39
|
use constant ARG => 2; # associated argument |
|
8
|
|
|
|
|
13
|
|
|
8
|
|
|
|
|
344
|
|
119
|
8
|
|
|
8
|
|
98
|
use constant EVENT => 3; # start/end event |
|
8
|
|
|
|
|
14
|
|
|
8
|
|
|
|
|
563
|
|
120
|
8
|
|
|
8
|
|
39
|
use constant TOP => -1; # access to the TOP element of a stack |
|
8
|
|
|
|
|
13
|
|
|
8
|
|
|
|
|
2956
|
|
121
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
# Actually export stuff... |
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
@RTF::Control::EXPORT = qw( |
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
output |
127
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
%symbol |
129
|
|
|
|
|
|
|
%info |
130
|
|
|
|
|
|
|
%do_on_event |
131
|
|
|
|
|
|
|
%do_on_control |
132
|
|
|
|
|
|
|
%par_props |
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
$style |
135
|
|
|
|
|
|
|
$newstyle |
136
|
|
|
|
|
|
|
$event |
137
|
|
|
|
|
|
|
$text |
138
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
SELF |
140
|
|
|
|
|
|
|
CONTROL |
141
|
|
|
|
|
|
|
ARG |
142
|
|
|
|
|
|
|
EVENT |
143
|
|
|
|
|
|
|
TOP |
144
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
); |
146
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
# Flags to specify where we are... Because this is all undocumented |
148
|
|
|
|
|
|
|
# I feel justified putting these into a hash at some point in the |
149
|
|
|
|
|
|
|
# near future... They also shouldn't be package variables, they |
150
|
|
|
|
|
|
|
# should be class variables, but, to be honest, trying to rid this |
151
|
|
|
|
|
|
|
# module of package variables seems an exercise in futility if I'm |
152
|
|
|
|
|
|
|
# actually trying to maintain the interface... I could internalise |
153
|
|
|
|
|
|
|
# everything that isn't part of the API though |
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
my $IN_STYLESHEET = 0; # inside or outside style table |
156
|
|
|
|
|
|
|
my $IN_FONTTBL = 0; # inside or outside font table |
157
|
|
|
|
|
|
|
my $IN_TABLE = 0; |
158
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
# Declare where we're going to be holding meta-data etc |
160
|
|
|
|
|
|
|
my %fonttbl; |
161
|
|
|
|
|
|
|
my %stylesheet; |
162
|
|
|
|
|
|
|
my %colortbl; |
163
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
# Property stacks |
165
|
|
|
|
|
|
|
my @par_props_stack = (); # stack of paragraph properties |
166
|
|
|
|
|
|
|
my @char_props_stack = (); # stack of character properties |
167
|
|
|
|
|
|
|
my @control = (); # stack of control instructions, rename control_stack |
168
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
# Some other stuff |
170
|
|
|
|
|
|
|
my $stylename = ''; |
171
|
|
|
|
|
|
|
my $cstylename = ''; # previous encountered style |
172
|
|
|
|
|
|
|
my $cli = 0; # current line indent value |
173
|
|
|
|
|
|
|
my $styledef = ''; |
174
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
=head2 new |
176
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
Returns an RTF::Control object. RTF::Control is a subclass of RTF::Parser. |
178
|
|
|
|
|
|
|
Internally, we call RTF::Parser's new() method, and then we call an internal |
179
|
|
|
|
|
|
|
method called _configure(), which takes care of options we were passed. |
180
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
ADD STUFF ON -output AND -confdir |
182
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
=cut |
184
|
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
sub new { |
186
|
|
|
|
|
|
|
|
187
|
9
|
|
|
9
|
1
|
196
|
my $proto = shift; |
188
|
9
|
|
33
|
|
|
86
|
my $class = ref($proto) || $proto; |
189
|
|
|
|
|
|
|
|
190
|
9
|
|
|
|
|
110
|
my $self = $class->SUPER::new(@_); |
191
|
|
|
|
|
|
|
|
192
|
9
|
|
|
|
|
76
|
$self->_configure(@_); |
193
|
|
|
|
|
|
|
|
194
|
9
|
|
|
|
|
36
|
return $self; |
195
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
} |
197
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
# This is a private method. It accepts a hash (well, a list) |
199
|
|
|
|
|
|
|
# of values, and stores them. If one of them is 'output', |
200
|
|
|
|
|
|
|
# it calls a function I'm yet to examine. This was done |
201
|
|
|
|
|
|
|
# in a horrendous way - it's now a lot tidier. :-) |
202
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
sub _configure { |
204
|
|
|
|
|
|
|
|
205
|
14
|
|
|
14
|
|
3462
|
my $self = shift; |
206
|
|
|
|
|
|
|
|
207
|
14
|
|
|
|
|
52
|
my %options = @_; |
208
|
|
|
|
|
|
|
|
209
|
|
|
|
|
|
|
# Sanitize the options |
210
|
14
|
|
|
|
|
25
|
my %clean_options; |
211
|
14
|
|
|
|
|
46
|
for my $key ( keys %options ) { |
212
|
|
|
|
|
|
|
|
213
|
12
|
|
|
|
|
25
|
my $oldkey = $key; |
214
|
|
|
|
|
|
|
|
215
|
12
|
|
|
|
|
42
|
$key =~ s/^-//; |
216
|
12
|
|
|
|
|
35
|
$key = lc($key); |
217
|
|
|
|
|
|
|
|
218
|
12
|
|
|
|
|
48
|
$clean_options{$key} = $options{$oldkey} |
219
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
} |
221
|
|
|
|
|
|
|
|
222
|
14
|
|
|
|
|
108
|
$self->{'_RTF_Control_Options'} = \%clean_options; |
223
|
|
|
|
|
|
|
|
224
|
14
|
100
|
|
|
|
111
|
$self->set_top_output_to( $clean_options{'output'} ) |
225
|
|
|
|
|
|
|
if $clean_options{'output'}; |
226
|
|
|
|
|
|
|
|
227
|
14
|
|
|
|
|
55
|
return $self; |
228
|
|
|
|
|
|
|
|
229
|
|
|
|
|
|
|
} |
230
|
|
|
|
|
|
|
|
231
|
8
|
|
|
8
|
|
43
|
use constant APPLICATION_DIR => 0; |
|
8
|
|
|
|
|
14
|
|
|
8
|
|
|
|
|
3367
|
|
232
|
|
|
|
|
|
|
|
233
|
|
|
|
|
|
|
=head2 application_dir |
234
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
I'm leaving this method in because removing it will cause a backward-compatability |
236
|
|
|
|
|
|
|
nightmare. This method returns the ( wait for it ) path that the .pm file corresponding |
237
|
|
|
|
|
|
|
to the class that the object is contained, without a trailing semi-colon. Obviously |
238
|
|
|
|
|
|
|
this is nasty in several ways. If you've set C<-confdir> in C that will be |
239
|
|
|
|
|
|
|
returned instead. You should definitely take that route if you're on an OS on which |
240
|
|
|
|
|
|
|
Perl can't use / as a directory seperator. |
241
|
|
|
|
|
|
|
|
242
|
|
|
|
|
|
|
=cut |
243
|
|
|
|
|
|
|
|
244
|
|
|
|
|
|
|
sub application_dir { |
245
|
|
|
|
|
|
|
|
246
|
|
|
|
|
|
|
# Grab our object |
247
|
1
|
|
|
1
|
1
|
5
|
my $self = shift; |
248
|
|
|
|
|
|
|
|
249
|
|
|
|
|
|
|
# Return -confdir if set |
250
|
1
|
50
|
|
|
|
11
|
return $self->{'_RTF_Control_Options'}->{'confdir'} |
251
|
|
|
|
|
|
|
if $self->{'_RTF_Control_Options'}->{'confdir'}; |
252
|
|
|
|
|
|
|
|
253
|
|
|
|
|
|
|
# Grab the class name |
254
|
0
|
|
|
|
|
0
|
my $class = ref $self; |
255
|
|
|
|
|
|
|
|
256
|
|
|
|
|
|
|
# Clean it up and look it up in %INC |
257
|
0
|
|
|
|
|
0
|
$class =~ s|::|/|g; |
258
|
0
|
|
|
|
|
0
|
$class = $INC{"$class.pm"}; |
259
|
|
|
|
|
|
|
|
260
|
0
|
|
|
|
|
0
|
return dirname $class; |
261
|
|
|
|
|
|
|
|
262
|
|
|
|
|
|
|
} |
263
|
|
|
|
|
|
|
|
264
|
|
|
|
|
|
|
=head2 charmap_reader |
265
|
|
|
|
|
|
|
|
266
|
|
|
|
|
|
|
This nicely abstracts away using application_dir and so on. It's a method |
267
|
|
|
|
|
|
|
call. It'll take the name of the class, and an argument for the module/file |
268
|
|
|
|
|
|
|
it's looking for. This is likely to be 'ansi' or 'charmap'. This argument, |
269
|
|
|
|
|
|
|
for historical reasons (ho ho ho) will have any _'s removed in the check for |
270
|
|
|
|
|
|
|
a module name ... C< $self->charmap_reader('char_map') > will thus look for, for |
271
|
|
|
|
|
|
|
example, C< RTF::TEXT::charmap > to load. It'll return the data in the file as |
272
|
|
|
|
|
|
|
an array of lines. This description sucks. |
273
|
|
|
|
|
|
|
|
274
|
|
|
|
|
|
|
=cut |
275
|
|
|
|
|
|
|
|
276
|
|
|
|
|
|
|
sub charmap_reader { |
277
|
|
|
|
|
|
|
|
278
|
7
|
|
|
7
|
1
|
3483
|
my $self = shift; |
279
|
7
|
|
|
|
|
10
|
my $file = shift; |
280
|
|
|
|
|
|
|
|
281
|
7
|
|
|
|
|
11
|
my @char_map_data; |
282
|
|
|
|
|
|
|
|
283
|
|
|
|
|
|
|
# Try and work out what our character set module would be called... |
284
|
7
|
|
|
|
|
9
|
my $module_file = $file; |
285
|
7
|
|
|
|
|
20
|
$module_file =~ s/_//g; |
286
|
7
|
|
|
|
|
95
|
my $module_name = ref($self) . '::' . $module_file; |
287
|
|
|
|
|
|
|
|
288
|
|
|
|
|
|
|
# Can we load it? |
289
|
7
|
|
|
31
|
|
548
|
eval "use $module_name"; |
|
31
|
|
|
7
|
|
110
|
|
|
7
|
|
|
10
|
|
14
|
|
|
7
|
|
|
5
|
|
86
|
|
|
4
|
|
|
|
|
13
|
|
|
4
|
|
|
|
|
10
|
|
|
4
|
|
|
|
|
32
|
|
|
7
|
|
|
|
|
25
|
|
|
4
|
|
|
|
|
8
|
|
|
4
|
|
|
|
|
24
|
|
|
4
|
|
|
|
|
25
|
|
|
4
|
|
|
|
|
8
|
|
|
4
|
|
|
|
|
21
|
|
290
|
|
|
|
|
|
|
|
291
|
|
|
|
|
|
|
# That would be a no... |
292
|
7
|
50
|
|
|
|
24
|
if ($@) { |
293
|
|
|
|
|
|
|
|
294
|
|
|
|
|
|
|
# Create a path for the charset file using the old method... |
295
|
0
|
|
|
|
|
0
|
my $charset_file = $_[SELF]->application_dir(__FILE__) . "/$file"; |
296
|
|
|
|
|
|
|
|
297
|
|
|
|
|
|
|
# Try and open it... |
298
|
0
|
0
|
|
|
|
0
|
open( CHAR_MAP, "< $charset_file" ) or |
299
|
|
|
|
|
|
|
die "Unable to open the charset file '$charset_file': $!"; |
300
|
|
|
|
|
|
|
|
301
|
|
|
|
|
|
|
# Read in the data... |
302
|
0
|
|
|
|
|
0
|
@char_map_data = (); |
303
|
|
|
|
|
|
|
|
304
|
|
|
|
|
|
|
# Why yes, yes we can... |
305
|
|
|
|
|
|
|
} else { |
306
|
|
|
|
|
|
|
|
307
|
7
|
|
|
|
|
18
|
my $sub_name = $module_name . '::' . 'data'; |
308
|
7
|
|
|
|
|
136
|
@char_map_data = main->$sub_name(); |
309
|
|
|
|
|
|
|
|
310
|
|
|
|
|
|
|
} |
311
|
|
|
|
|
|
|
|
312
|
7
|
|
|
|
|
171
|
return @char_map_data; |
313
|
|
|
|
|
|
|
|
314
|
|
|
|
|
|
|
} |
315
|
|
|
|
|
|
|
|
316
|
|
|
|
|
|
|
########################################################################### |
317
|
|
|
|
|
|
|
|
318
|
|
|
|
|
|
|
# This stuff is all to do with the stack, and I'm not really sure how it |
319
|
|
|
|
|
|
|
# works. I'm hoping it'll become more obvious as I go. The routines themselves |
320
|
|
|
|
|
|
|
# are now all documented, but who knows what the stack is or why? hrm? |
321
|
|
|
|
|
|
|
|
322
|
|
|
|
|
|
|
# This hurts my little brane. |
323
|
|
|
|
|
|
|
|
324
|
|
|
|
|
|
|
# Holds the output stack |
325
|
|
|
|
|
|
|
my @output_stack; |
326
|
|
|
|
|
|
|
|
327
|
|
|
|
|
|
|
# Defines how large the output stack can be |
328
|
8
|
|
|
8
|
|
41
|
use constant MAX_OUTPUT_STACK_SIZE => 0; # PV: 8 seems a good value |
|
8
|
|
|
|
|
17
|
|
|
8
|
|
|
|
|
2202
|
|
329
|
|
|
|
|
|
|
# PS: Then why not default it to that? |
330
|
|
|
|
|
|
|
|
331
|
|
|
|
|
|
|
=head1 Stack manipulation |
332
|
|
|
|
|
|
|
|
333
|
|
|
|
|
|
|
=head2 dump_stack |
334
|
|
|
|
|
|
|
|
335
|
|
|
|
|
|
|
Serializes and prints the stack to STDERR |
336
|
|
|
|
|
|
|
|
337
|
|
|
|
|
|
|
=cut |
338
|
|
|
|
|
|
|
|
339
|
|
|
|
|
|
|
# Serializes the stack, and prints it to STDERR. |
340
|
|
|
|
|
|
|
sub dump_stack { |
341
|
|
|
|
|
|
|
|
342
|
0
|
|
|
0
|
1
|
0
|
my $stack_size = @output_stack; |
343
|
|
|
|
|
|
|
|
344
|
0
|
|
|
|
|
0
|
print STDERR "Stack size: $stack_size\n"; |
345
|
|
|
|
|
|
|
|
346
|
0
|
|
|
|
|
0
|
print STDERR $stack_size-- . " |$_|\n" for reverse @output_stack; |
347
|
|
|
|
|
|
|
|
348
|
|
|
|
|
|
|
} |
349
|
|
|
|
|
|
|
|
350
|
|
|
|
|
|
|
=head2 output |
351
|
|
|
|
|
|
|
|
352
|
|
|
|
|
|
|
Holder routine for the current thing to do with output text we're given. |
353
|
|
|
|
|
|
|
It starts off as the same as C<$string_output_sub>, which adds the string |
354
|
|
|
|
|
|
|
to the element at the C of the output stack. However, the idea, I |
355
|
|
|
|
|
|
|
believe, is to allow that to be changed at will, using C. |
356
|
|
|
|
|
|
|
|
357
|
|
|
|
|
|
|
=cut |
358
|
|
|
|
|
|
|
|
359
|
|
|
|
|
|
|
sub output { |
360
|
|
|
|
|
|
|
|
361
|
52
|
50
|
|
52
|
1
|
229
|
$output_stack[TOP] .= $_[0] if defined $_[0]; |
362
|
|
|
|
|
|
|
|
363
|
|
|
|
|
|
|
} |
364
|
|
|
|
|
|
|
|
365
|
|
|
|
|
|
|
# I'm guessing (because I'm generous ;-) that this is done because |
366
|
|
|
|
|
|
|
# subclasses might want to modifiy the values of these. These are |
367
|
|
|
|
|
|
|
# obviously the two different ways to spit out ... something. We |
368
|
|
|
|
|
|
|
# start with the string_output_sub being what &output does tho. |
369
|
|
|
|
|
|
|
|
370
|
|
|
|
|
|
|
my $nul_output_sub = sub { |
371
|
|
|
|
|
|
|
#print STDERR "** $_[0] **\n"; |
372
|
|
|
|
|
|
|
}; |
373
|
|
|
|
|
|
|
|
374
|
|
|
|
|
|
|
my $string_output_sub = sub { |
375
|
|
|
|
|
|
|
|
376
|
9
|
100
|
|
3
|
|
30
|
$output_stack[TOP] .= $_[0] if $_[0]; |
377
|
|
|
|
|
|
|
|
378
|
|
|
|
|
|
|
}; |
379
|
|
|
|
|
|
|
|
380
|
|
|
|
|
|
|
=head2 push_output |
381
|
|
|
|
|
|
|
|
382
|
|
|
|
|
|
|
Adds a blank element to the end of the stack. It will change (or |
383
|
|
|
|
|
|
|
maintain) the function of C |
384
|
|
|
|
|
|
|
unless you pass it the argument C< 'nul' >, in which case it will |
385
|
|
|
|
|
|
|
set C |
386
|
|
|
|
|
|
|
|
387
|
|
|
|
|
|
|
=cut |
388
|
|
|
|
|
|
|
|
389
|
|
|
|
|
|
|
sub push_output { |
390
|
|
|
|
|
|
|
|
391
|
|
|
|
|
|
|
# If we've set a maximum output stack and then exceeded it, complain. |
392
|
55
|
|
|
55
|
1
|
61
|
if (MAX_OUTPUT_STACK_SIZE) { |
393
|
|
|
|
|
|
|
die "max size of output stack exceeded" |
394
|
|
|
|
|
|
|
if @output_stack == MAX_OUTPUT_STACK_SIZE; |
395
|
|
|
|
|
|
|
} |
396
|
|
|
|
|
|
|
|
397
|
|
|
|
|
|
|
# If we didn't get an argument, output becomes string... |
398
|
55
|
100
|
|
|
|
182
|
unless ( defined( $_[0] ) ) { |
|
|
50
|
|
|
|
|
|
399
|
|
|
|
|
|
|
|
400
|
8
|
|
|
8
|
|
42
|
no warnings 'redefine'; |
|
8
|
|
|
|
|
12
|
|
|
8
|
|
|
|
|
521
|
|
401
|
49
|
|
|
|
|
98
|
*output = $string_output_sub; |
402
|
|
|
|
|
|
|
|
403
|
|
|
|
|
|
|
# If we were given 'nul', set output to $nul_output_sub |
404
|
|
|
|
|
|
|
} elsif ( $_[0] eq 'nul' ) { |
405
|
|
|
|
|
|
|
|
406
|
8
|
|
|
8
|
|
37
|
no warnings 'redefine'; |
|
8
|
|
|
|
|
12
|
|
|
8
|
|
|
|
|
898
|
|
407
|
6
|
|
|
|
|
28
|
*output = $nul_output_sub; |
408
|
|
|
|
|
|
|
|
409
|
|
|
|
|
|
|
} |
410
|
|
|
|
|
|
|
|
411
|
|
|
|
|
|
|
# Add an empty element to the end of the ouput stack |
412
|
55
|
|
|
|
|
116
|
push @output_stack, ''; |
413
|
|
|
|
|
|
|
|
414
|
|
|
|
|
|
|
} |
415
|
|
|
|
|
|
|
|
416
|
|
|
|
|
|
|
=head2 pop_output |
417
|
|
|
|
|
|
|
|
418
|
|
|
|
|
|
|
Removes and returns the last element of the ouput stack |
419
|
|
|
|
|
|
|
|
420
|
|
|
|
|
|
|
=cut |
421
|
|
|
|
|
|
|
|
422
|
|
|
|
|
|
|
# Remove and return an element of the output stack, which |
423
|
|
|
|
|
|
|
# should basically be the in-scope text... See how &do_on_info |
424
|
|
|
|
|
|
|
# uses this |
425
|
|
|
|
|
|
|
|
426
|
|
|
|
|
|
|
sub pop_output { |
427
|
|
|
|
|
|
|
|
428
|
34
|
|
|
34
|
1
|
105
|
pop @output_stack; |
429
|
|
|
|
|
|
|
|
430
|
|
|
|
|
|
|
} |
431
|
|
|
|
|
|
|
|
432
|
8
|
|
|
8
|
|
41
|
use constant SET_TOP_OUTPUT_TO_TRACE => 0; |
|
8
|
|
|
|
|
15
|
|
|
8
|
|
|
|
|
1144
|
|
433
|
|
|
|
|
|
|
|
434
|
|
|
|
|
|
|
=head2 set_top_output_to |
435
|
|
|
|
|
|
|
|
436
|
|
|
|
|
|
|
Only called at init time, is a method call not a function. |
437
|
|
|
|
|
|
|
Sets the action of C, depending on whether |
438
|
|
|
|
|
|
|
you pass it a filehandle or string reference. |
439
|
|
|
|
|
|
|
|
440
|
|
|
|
|
|
|
=cut |
441
|
|
|
|
|
|
|
|
442
|
|
|
|
|
|
|
# Sets flush_top_output to print to the appropriate thingy |
443
|
|
|
|
|
|
|
sub set_top_output_to { |
444
|
|
|
|
|
|
|
|
445
|
6
|
|
|
6
|
1
|
13
|
my $self = shift; |
446
|
|
|
|
|
|
|
|
447
|
|
|
|
|
|
|
# Are we being passed a filehandle? |
448
|
|
|
|
|
|
|
|
449
|
6
|
|
|
|
|
20
|
local *X = $_[0]; |
450
|
|
|
|
|
|
|
|
451
|
6
|
100
|
|
|
|
36
|
if ( fileno X ) { |
|
|
50
|
|
|
|
|
|
452
|
|
|
|
|
|
|
|
453
|
2
|
|
|
|
|
4
|
my $stream = *X; |
454
|
|
|
|
|
|
|
|
455
|
|
|
|
|
|
|
# Debugging info if asked for |
456
|
2
|
|
|
|
|
3
|
print STDERR "stream: ", fileno X, "\n" if SET_TOP_OUTPUT_TO_TRACE; |
457
|
|
|
|
|
|
|
|
458
|
|
|
|
|
|
|
# Turn off warnings |
459
|
8
|
|
|
8
|
|
38
|
no warnings 'redefine'; |
|
8
|
|
|
|
|
14
|
|
|
8
|
|
|
|
|
1120
|
|
460
|
|
|
|
|
|
|
|
461
|
|
|
|
|
|
|
# Overwrite &flush_top_output |
462
|
|
|
|
|
|
|
*flush_top_output = sub { |
463
|
0
|
|
|
0
|
|
0
|
print $stream $output_stack[TOP]; |
464
|
0
|
|
|
|
|
0
|
$output_stack[TOP] = ''; |
465
|
2
|
|
|
|
|
27
|
}; |
466
|
|
|
|
|
|
|
|
467
|
|
|
|
|
|
|
# We've been passed a reference to a scalar... |
468
|
|
|
|
|
|
|
|
469
|
|
|
|
|
|
|
} elsif ( ref $_[0] eq 'SCALAR' ) { |
470
|
|
|
|
|
|
|
|
471
|
4
|
|
|
|
|
8
|
print STDERR "output to string\n" if SET_TOP_OUTPUT_TO_TRACE; |
472
|
|
|
|
|
|
|
|
473
|
4
|
|
|
|
|
7
|
my $content_ref = $_[0]; |
474
|
|
|
|
|
|
|
|
475
|
8
|
|
|
8
|
|
40
|
no warnings 'redefine'; |
|
8
|
|
|
|
|
21
|
|
|
8
|
|
|
|
|
1332
|
|
476
|
|
|
|
|
|
|
|
477
|
|
|
|
|
|
|
*flush_top_output = sub { |
478
|
25
|
|
|
25
|
|
44
|
$$content_ref .= $output_stack[TOP]; |
479
|
25
|
|
|
|
|
47
|
$output_stack[TOP] = ''; |
480
|
4
|
|
|
|
|
56
|
}; |
481
|
|
|
|
|
|
|
|
482
|
|
|
|
|
|
|
# Someone's done something weird |
483
|
|
|
|
|
|
|
|
484
|
|
|
|
|
|
|
} else { |
485
|
|
|
|
|
|
|
|
486
|
0
|
|
|
|
|
0
|
warn "unknown output specification: $_[0]\n"; |
487
|
|
|
|
|
|
|
|
488
|
|
|
|
|
|
|
} |
489
|
|
|
|
|
|
|
|
490
|
|
|
|
|
|
|
} |
491
|
|
|
|
|
|
|
|
492
|
|
|
|
|
|
|
# the default prints on the selected output filehandle |
493
|
|
|
|
|
|
|
|
494
|
|
|
|
|
|
|
=head2 flush_top_output |
495
|
|
|
|
|
|
|
|
496
|
|
|
|
|
|
|
Output the top element of the stack in the way specified by the call |
497
|
|
|
|
|
|
|
to C |
498
|
|
|
|
|
|
|
|
499
|
|
|
|
|
|
|
=cut |
500
|
|
|
|
|
|
|
|
501
|
|
|
|
|
|
|
sub flush_top_output { |
502
|
|
|
|
|
|
|
|
503
|
0
|
|
|
0
|
1
|
0
|
print $output_stack[TOP]; |
504
|
0
|
|
|
|
|
0
|
$output_stack[TOP] = ''; |
505
|
|
|
|
|
|
|
|
506
|
|
|
|
|
|
|
} |
507
|
|
|
|
|
|
|
|
508
|
|
|
|
|
|
|
########################################################################### |
509
|
|
|
|
|
|
|
# Trace management |
510
|
8
|
|
|
8
|
|
46
|
use constant RTF_DEBUG => 0; |
|
8
|
|
|
|
|
20
|
|
|
8
|
|
|
|
|
367
|
|
511
|
8
|
|
|
8
|
|
36
|
use constant TRACE => 0; |
|
8
|
|
|
|
|
16
|
|
|
8
|
|
|
|
|
356
|
|
512
|
8
|
|
|
8
|
|
38
|
use constant STACK_TRACE => 0; # |
|
8
|
|
|
|
|
12
|
|
|
8
|
|
|
|
|
308
|
|
513
|
8
|
|
|
|
|
343
|
use constant STYLESHEET_TRACE => |
514
|
8
|
|
|
8
|
|
33
|
0; # If you want to see the stylesheet of the document |
|
8
|
|
|
|
|
19
|
|
515
|
8
|
|
|
8
|
|
37
|
use constant STYLE_TRACE => 0; # |
|
8
|
|
|
|
|
12
|
|
|
8
|
|
|
|
|
322
|
|
516
|
8
|
|
|
8
|
|
38
|
use constant LIST_TRACE => 0; |
|
8
|
|
|
|
|
12
|
|
|
8
|
|
|
|
|
1523
|
|
517
|
|
|
|
|
|
|
|
518
|
|
|
|
|
|
|
$| = 1 if TRACE or STACK_TRACE or RTF_DEBUG; |
519
|
|
|
|
|
|
|
|
520
|
|
|
|
|
|
|
# Debugging function - prints the number of _'s matching |
521
|
|
|
|
|
|
|
# the number of controls in our current control stack, |
522
|
|
|
|
|
|
|
# and anything else we were passed, and the $. - input |
523
|
|
|
|
|
|
|
# line number. |
524
|
|
|
|
|
|
|
|
525
|
|
|
|
|
|
|
sub trace { |
526
|
|
|
|
|
|
|
#my(@caller) = (caller(1)); |
527
|
|
|
|
|
|
|
#my $sub = (@caller)[3]; |
528
|
|
|
|
|
|
|
#$sub =~ s/.*:://; |
529
|
|
|
|
|
|
|
#$sub = sprintf "%-12s", $sub; |
530
|
0
|
0
|
|
0
|
0
|
0
|
shift if ref $_[0]; |
531
|
0
|
|
|
|
|
0
|
print STDERR "[$.]", ( '_' x $#control . "@_\n" ); |
532
|
|
|
|
|
|
|
} |
533
|
|
|
|
|
|
|
$SIG{__DIE__} = sub { |
534
|
|
|
|
|
|
|
require Carp; |
535
|
|
|
|
|
|
|
Carp::confess; |
536
|
|
|
|
|
|
|
} |
537
|
|
|
|
|
|
|
if RTF_DEBUG; |
538
|
|
|
|
|
|
|
|
539
|
|
|
|
|
|
|
########################################################################### |
540
|
|
|
|
|
|
|
# Some generic routines |
541
|
8
|
|
|
8
|
|
40
|
use constant DISCARD_CONTENT => 0; |
|
8
|
|
|
|
|
12
|
|
|
8
|
|
|
|
|
7527
|
|
542
|
|
|
|
|
|
|
|
543
|
|
|
|
|
|
|
# This seems to be what we do when we hit a control word |
544
|
|
|
|
|
|
|
# we're not going to parse. He seems to be manually |
545
|
|
|
|
|
|
|
# implementing this some times - I wonder why? |
546
|
|
|
|
|
|
|
|
547
|
|
|
|
|
|
|
sub discard_content { |
548
|
|
|
|
|
|
|
|
549
|
|
|
|
|
|
|
# Read in information about the control word we hit |
550
|
0
|
|
|
0
|
0
|
0
|
my ( $control, $arg, $cevent ) = ( $_[CONTROL], $_[ARG], $_[EVENT] ); |
551
|
|
|
|
|
|
|
|
552
|
0
|
|
|
|
|
0
|
trace "($_[CONTROL], $_[ARG], $_[EVENT])" if DISCARD_CONTENT; |
553
|
|
|
|
|
|
|
|
554
|
|
|
|
|
|
|
# This I don't understand. Presumably if we've hit 0, then it's |
555
|
|
|
|
|
|
|
# the close of a part of the document being dictated by a char |
556
|
|
|
|
|
|
|
# property, like, say, \b1I'm bold\b0 I'm not. |
557
|
|
|
|
|
|
|
|
558
|
0
|
0
|
0
|
|
|
0
|
if ( defined $arg && $_[ARG] eq "0" ) { |
|
|
0
|
0
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
559
|
|
|
|
|
|
|
|
560
|
|
|
|
|
|
|
# Remove the last element on the output stack |
561
|
0
|
|
|
|
|
0
|
pop_output(); |
562
|
|
|
|
|
|
|
|
563
|
|
|
|
|
|
|
# Set the property as on(?) on the control stack |
564
|
|
|
|
|
|
|
# This should probably be a 0. Something to test |
565
|
|
|
|
|
|
|
# later. |
566
|
0
|
|
|
|
|
0
|
$control[TOP]->{"$_[CONTROL]1"} = 1; |
567
|
|
|
|
|
|
|
|
568
|
|
|
|
|
|
|
# Add a blank element to the end of the output stack |
569
|
|
|
|
|
|
|
} elsif ( $_[EVENT] eq 'start' ) { |
570
|
|
|
|
|
|
|
|
571
|
0
|
|
|
|
|
0
|
push_output(); |
572
|
0
|
|
|
|
|
0
|
$control[TOP]->{"$_[CONTROL]$_[ARG]"} = 1; |
573
|
|
|
|
|
|
|
|
574
|
|
|
|
|
|
|
} elsif ( defined $arg && $_[ARG] eq "1" ) { |
575
|
0
|
|
|
|
|
0
|
$cevent = 'start'; |
576
|
0
|
|
|
|
|
0
|
push_output(); |
577
|
|
|
|
|
|
|
|
578
|
|
|
|
|
|
|
} elsif ( $_[EVENT] eq 'end' ) { # End of discard |
579
|
|
|
|
|
|
|
|
580
|
0
|
|
|
|
|
0
|
my $string = pop_output(); |
581
|
|
|
|
|
|
|
|
582
|
0
|
0
|
|
|
|
0
|
if ( length $string > 30 ) { |
583
|
0
|
|
|
|
|
0
|
$string =~ s/(.{1,10}).*(.{1,10})/$1 ... $2/; |
584
|
|
|
|
|
|
|
} |
585
|
|
|
|
|
|
|
|
586
|
0
|
|
|
|
|
0
|
trace "discard content of \\$control: $string" if DISCARD_CONTENT; |
587
|
|
|
|
|
|
|
|
588
|
|
|
|
|
|
|
} else { |
589
|
|
|
|
|
|
|
|
590
|
0
|
|
|
|
|
0
|
die "($_[CONTROL], $_[ARG], $_[EVENT])" if DISCARD_CONTENT; |
591
|
|
|
|
|
|
|
|
592
|
|
|
|
|
|
|
} |
593
|
|
|
|
|
|
|
|
594
|
|
|
|
|
|
|
} |
595
|
|
|
|
|
|
|
|
596
|
|
|
|
|
|
|
# Document meta-data collator. Whenever we hit an info group, |
597
|
|
|
|
|
|
|
# this sub is called. All it does is put all the text 'in-scope' |
598
|
|
|
|
|
|
|
# into the %info hash... |
599
|
|
|
|
|
|
|
|
600
|
|
|
|
|
|
|
sub do_on_info { |
601
|
|
|
|
|
|
|
|
602
|
0
|
|
|
0
|
0
|
0
|
my $string; |
603
|
0
|
|
0
|
|
|
0
|
my $arg = $_[ARG] || ''; |
604
|
|
|
|
|
|
|
|
605
|
0
|
0
|
|
|
|
0
|
if ( $_[EVENT] eq 'start' ) { |
606
|
|
|
|
|
|
|
|
607
|
0
|
|
|
|
|
0
|
push_output(); |
608
|
0
|
|
|
|
|
0
|
$control[TOP]->{"$_[CONTROL]$arg"} = 1; |
609
|
|
|
|
|
|
|
|
610
|
|
|
|
|
|
|
} else { |
611
|
|
|
|
|
|
|
|
612
|
0
|
|
|
|
|
0
|
$string = pop_output(); |
613
|
0
|
|
|
|
|
0
|
$info{"$_[CONTROL]$arg"} = $string; |
614
|
|
|
|
|
|
|
|
615
|
|
|
|
|
|
|
} |
616
|
|
|
|
|
|
|
} |
617
|
|
|
|
|
|
|
|
618
|
|
|
|
|
|
|
# SYMBOLS |
619
|
|
|
|
|
|
|
# default mapping for symbols |
620
|
|
|
|
|
|
|
# char processed by the parser symbol() callback: - _ ~ : | { } * ' \\ |
621
|
|
|
|
|
|
|
%symbol = qw( |
622
|
|
|
|
|
|
|
| | |
623
|
|
|
|
|
|
|
_ _ |
624
|
|
|
|
|
|
|
: : |
625
|
|
|
|
|
|
|
bullet * |
626
|
|
|
|
|
|
|
endash - |
627
|
|
|
|
|
|
|
emdash -- |
628
|
|
|
|
|
|
|
ldblquote `` |
629
|
|
|
|
|
|
|
rdblquote '' |
630
|
|
|
|
|
|
|
); |
631
|
|
|
|
|
|
|
$symbol{rquote} = "\'"; |
632
|
|
|
|
|
|
|
$symbol{lquote} = "\`"; |
633
|
|
|
|
|
|
|
$symbol{'column'} = "\t"; |
634
|
|
|
|
|
|
|
$symbol{'tab'} = "\t"; |
635
|
|
|
|
|
|
|
$symbol{'line'} = "\n"; |
636
|
|
|
|
|
|
|
$symbol{'page'} = "\f"; |
637
|
|
|
|
|
|
|
|
638
|
|
|
|
|
|
|
# Handler for symbols - prints the symbol corresponding |
639
|
|
|
|
|
|
|
# to our first argument... |
640
|
|
|
|
|
|
|
|
641
|
|
|
|
|
|
|
sub do_on_symbol { |
642
|
|
|
|
|
|
|
|
643
|
0
|
|
|
0
|
0
|
0
|
output $symbol{ $_[CONTROL] }; |
644
|
|
|
|
|
|
|
|
645
|
|
|
|
|
|
|
} |
646
|
|
|
|
|
|
|
|
647
|
|
|
|
|
|
|
my %symbol_ctrl = map { # install the do_on_symbol() routine |
648
|
|
|
|
|
|
|
if (/^[a-z]+$/) { |
649
|
|
|
|
|
|
|
$_ => \&do_on_symbol; |
650
|
|
|
|
|
|
|
} else { |
651
|
|
|
|
|
|
|
'undef' => undef; |
652
|
|
|
|
|
|
|
} |
653
|
|
|
|
|
|
|
} keys %symbol; |
654
|
|
|
|
|
|
|
|
655
|
|
|
|
|
|
|
########################################################################################### |
656
|
|
|
|
|
|
|
my %char_props; # control hash must be declarated before install_callback() |
657
|
|
|
|
|
|
|
# purpose: associate callbacks to controls |
658
|
|
|
|
|
|
|
# 1. an hash name that contains the controls |
659
|
|
|
|
|
|
|
# 2. a callback name |
660
|
|
|
|
|
|
|
|
661
|
|
|
|
|
|
|
# Sets the call back given as the second argument |
662
|
|
|
|
|
|
|
# as the %do_on_control for all controls currently |
663
|
|
|
|
|
|
|
# in %char_props. DON'T UNDERSTAND. |
664
|
|
|
|
|
|
|
|
665
|
|
|
|
|
|
|
sub install_callback { # not a method!!! |
666
|
|
|
|
|
|
|
|
667
|
8
|
|
|
8
|
0
|
23
|
my ( $control, $callback ) = ( $_[1], $_[2] ); |
668
|
8
|
|
|
8
|
|
57
|
no strict 'refs'; |
|
8
|
|
|
|
|
10
|
|
|
8
|
|
|
|
|
1469
|
|
669
|
8
|
50
|
|
|
|
81
|
unless (%char_props) { # why I can't write %{$control} |
670
|
0
|
|
|
|
|
0
|
die "'%$control' not defined"; |
671
|
|
|
|
|
|
|
} |
672
|
8
|
|
|
|
|
39
|
for ( keys %char_props ) { |
673
|
48
|
|
|
|
|
50
|
$do_on_control{$_} = \&{$callback}; |
|
48
|
|
|
|
|
119
|
|
674
|
|
|
|
|
|
|
} |
675
|
|
|
|
|
|
|
} |
676
|
|
|
|
|
|
|
# TOGGLES |
677
|
|
|
|
|
|
|
# {\ ...} |
678
|
|
|
|
|
|
|
# {\0 ...} |
679
|
|
|
|
|
|
|
########################################################################### |
680
|
|
|
|
|
|
|
# How to give a general definition? |
681
|
|
|
|
|
|
|
#my %control_definition = ( # control => [default_value nassociated_callback] |
682
|
|
|
|
|
|
|
# 'char_props' => qw(0 do_on_control), |
683
|
|
|
|
|
|
|
# ); |
684
|
|
|
|
|
|
|
|
685
|
|
|
|
|
|
|
# Remove character formatting properties ... there are actually more |
686
|
|
|
|
|
|
|
# character formatting properties defined in the RTF spec, but |
687
|
|
|
|
|
|
|
# these seem to be the ones supported by this module... |
688
|
|
|
|
|
|
|
|
689
|
|
|
|
|
|
|
sub reset_char_props { |
690
|
|
|
|
|
|
|
|
691
|
54
|
|
|
|
|
167
|
%char_props = map { |
692
|
|
|
|
|
|
|
|
693
|
9
|
|
|
9
|
0
|
23
|
$_ => 0 |
694
|
|
|
|
|
|
|
|
695
|
|
|
|
|
|
|
} qw(b i ul sub super strike); |
696
|
|
|
|
|
|
|
} |
697
|
|
|
|
|
|
|
|
698
|
|
|
|
|
|
|
my $char_prop_change = 0; |
699
|
|
|
|
|
|
|
my %current_char_props = %char_props; |
700
|
8
|
|
|
8
|
|
41
|
use constant OUTPUT_CHAR_PROPS => 0; |
|
8
|
|
|
|
|
13
|
|
|
8
|
|
|
|
|
1897
|
|
701
|
|
|
|
|
|
|
|
702
|
|
|
|
|
|
|
# Force a START or END event on our current character |
703
|
|
|
|
|
|
|
# properties... This is a method call. |
704
|
|
|
|
|
|
|
|
705
|
|
|
|
|
|
|
sub force_char_props { # force a START/END event |
706
|
|
|
|
|
|
|
|
707
|
|
|
|
|
|
|
# Obviously you're not allowed to do this in the fonttable |
708
|
|
|
|
|
|
|
# or style sheet... |
709
|
|
|
|
|
|
|
|
710
|
5
|
100
|
66
|
5
|
0
|
29
|
return if $IN_STYLESHEET or $IN_FONTTBL; |
711
|
|
|
|
|
|
|
|
712
|
4
|
|
|
|
|
7
|
trace "@_" if OUTPUT_CHAR_PROPS; |
713
|
|
|
|
|
|
|
|
714
|
|
|
|
|
|
|
# [0] is our object |
715
|
4
|
|
|
|
|
7
|
$event = $_[1]; # END or START |
716
|
|
|
|
|
|
|
# close or open all activated char prorperties |
717
|
|
|
|
|
|
|
|
718
|
4
|
|
|
|
|
8
|
push_output(); |
719
|
|
|
|
|
|
|
|
720
|
4
|
|
|
|
|
15
|
while ( my ( $char_prop, $value ) = each %char_props ) { |
721
|
|
|
|
|
|
|
|
722
|
24
|
50
|
|
|
|
84
|
next unless $value; |
723
|
|
|
|
|
|
|
|
724
|
0
|
|
|
|
|
0
|
trace "$event active char props: $char_prop" if OUTPUT_CHAR_PROPS; |
725
|
|
|
|
|
|
|
|
726
|
0
|
0
|
|
|
|
0
|
if ( defined( my $action = $do_on_event{$char_prop} ) ) { |
727
|
|
|
|
|
|
|
|
728
|
0
|
|
|
|
|
0
|
( $style, $event ) = ( $char_prop, $event ); |
729
|
|
|
|
|
|
|
|
730
|
0
|
|
|
|
|
0
|
&$action; |
731
|
|
|
|
|
|
|
|
732
|
|
|
|
|
|
|
} |
733
|
|
|
|
|
|
|
|
734
|
0
|
|
|
|
|
0
|
$current_char_props{$char_prop} = $value; |
735
|
|
|
|
|
|
|
|
736
|
|
|
|
|
|
|
} |
737
|
|
|
|
|
|
|
|
738
|
4
|
|
|
|
|
9
|
$char_prop_change = 0; |
739
|
|
|
|
|
|
|
|
740
|
4
|
|
|
|
|
10
|
pop_output(); |
741
|
|
|
|
|
|
|
|
742
|
|
|
|
|
|
|
} |
743
|
|
|
|
|
|
|
|
744
|
8
|
|
|
8
|
|
44
|
use constant PROCESS_CHAR_PROPS => 0; |
|
8
|
|
|
|
|
16
|
|
|
8
|
|
|
|
|
2231
|
|
745
|
|
|
|
|
|
|
|
746
|
|
|
|
|
|
|
# Only run outside of stylesheets and fonttables, |
747
|
|
|
|
|
|
|
# and only when the $char_prop_change flag is |
748
|
|
|
|
|
|
|
# set. |
749
|
|
|
|
|
|
|
|
750
|
|
|
|
|
|
|
sub process_char_props { |
751
|
|
|
|
|
|
|
|
752
|
32
|
100
|
66
|
32
|
0
|
201
|
return if $IN_STYLESHEET or $IN_FONTTBL; |
753
|
|
|
|
|
|
|
|
754
|
26
|
100
|
|
|
|
72
|
return unless $char_prop_change; |
755
|
|
|
|
|
|
|
|
756
|
|
|
|
|
|
|
# Add a new output block |
757
|
|
|
|
|
|
|
|
758
|
20
|
|
|
|
|
37
|
push_output(); |
759
|
|
|
|
|
|
|
|
760
|
|
|
|
|
|
|
# Go through char_props (is the what we were, or what we're going to?!) |
761
|
20
|
|
|
|
|
65
|
while ( my ( $char_prop, $value ) = each %char_props ) { |
762
|
|
|
|
|
|
|
|
763
|
|
|
|
|
|
|
# Get the current character property |
764
|
120
|
|
|
|
|
154
|
my $prop = $current_char_props{$char_prop}; |
765
|
|
|
|
|
|
|
|
766
|
|
|
|
|
|
|
# Set it to an explicit 0 if not set |
767
|
120
|
100
|
|
|
|
188
|
$prop = defined $prop ? $prop : 0; |
768
|
|
|
|
|
|
|
|
769
|
120
|
|
|
|
|
103
|
trace "$char_prop $value" if PROCESS_CHAR_PROPS; |
770
|
|
|
|
|
|
|
|
771
|
|
|
|
|
|
|
# If the values in %char_props and $current_char_props don't match.. |
772
|
120
|
100
|
|
|
|
408
|
if ( $prop != $value ) { |
773
|
|
|
|
|
|
|
|
774
|
|
|
|
|
|
|
# See if we have an event... |
775
|
14
|
50
|
|
|
|
38
|
if ( defined( my $action = $do_on_event{$char_prop} ) ) { |
776
|
|
|
|
|
|
|
|
777
|
|
|
|
|
|
|
# Set event to start or end depending on if |
778
|
|
|
|
|
|
|
# the $value is a literal 1. |
779
|
14
|
100
|
|
|
|
32
|
$event = $value == 1 ? 'start' : 'end'; |
780
|
|
|
|
|
|
|
|
781
|
14
|
|
|
|
|
27
|
( $style, $event ) = ( $char_prop, $event ); |
782
|
|
|
|
|
|
|
|
783
|
|
|
|
|
|
|
# Fire the event |
784
|
14
|
|
|
|
|
36
|
&$action; |
785
|
|
|
|
|
|
|
|
786
|
|
|
|
|
|
|
} |
787
|
|
|
|
|
|
|
|
788
|
|
|
|
|
|
|
# Set the $current_char_props to equal what was in %char_props |
789
|
14
|
|
|
|
|
156
|
$current_char_props{$char_prop} = $value; |
790
|
|
|
|
|
|
|
|
791
|
|
|
|
|
|
|
} |
792
|
|
|
|
|
|
|
|
793
|
120
|
|
|
|
|
345
|
trace "$char_prop - $prop - $value" if PROCESS_CHAR_PROPS; |
794
|
|
|
|
|
|
|
|
795
|
|
|
|
|
|
|
} |
796
|
|
|
|
|
|
|
|
797
|
|
|
|
|
|
|
# Reset the flag |
798
|
20
|
|
|
|
|
23
|
$char_prop_change = 0; |
799
|
|
|
|
|
|
|
|
800
|
|
|
|
|
|
|
# Return whatever was on the stack |
801
|
20
|
|
|
|
|
46
|
pop_output(); |
802
|
|
|
|
|
|
|
|
803
|
|
|
|
|
|
|
} |
804
|
|
|
|
|
|
|
|
805
|
8
|
|
|
8
|
|
42
|
use constant DO_ON_CHAR_PROP => 0; |
|
8
|
|
|
|
|
16
|
|
|
8
|
|
|
|
|
2688
|
|
806
|
|
|
|
|
|
|
|
807
|
|
|
|
|
|
|
# Again, not called in a font or stylesheet, for obvious reasons. |
808
|
|
|
|
|
|
|
# Set the char_prop_change flag. If the argument is '0', we set |
809
|
|
|
|
|
|
|
# that character property to that - if the event is start, we set |
810
|
|
|
|
|
|
|
# it to one, otherwise we throw a warning. |
811
|
|
|
|
|
|
|
|
812
|
|
|
|
|
|
|
sub do_on_char_prop { # associated callback |
813
|
|
|
|
|
|
|
|
814
|
11
|
50
|
33
|
11
|
0
|
57
|
return if $IN_STYLESHEET or $IN_FONTTBL; |
815
|
|
|
|
|
|
|
|
816
|
11
|
|
|
|
|
35
|
my ( $control, $arg, $cevent ) = ( $_[CONTROL], $_[ARG], $_[EVENT] ); |
817
|
|
|
|
|
|
|
|
818
|
11
|
|
|
|
|
81
|
trace "my(\$control, \$arg, \$cevent) = ($_[CONTROL], $_[ARG], $_[EVENT]);" |
819
|
|
|
|
|
|
|
if DO_ON_CHAR_PROP; |
820
|
|
|
|
|
|
|
|
821
|
11
|
|
|
|
|
70
|
$char_prop_change = 1; |
822
|
|
|
|
|
|
|
|
823
|
11
|
100
|
66
|
|
|
121
|
if ( defined( $_[ARG] ) and $_[ARG] eq "0" ) { # \b0 |
|
|
50
|
|
|
|
|
|
824
|
|
|
|
|
|
|
|
825
|
2
|
|
|
|
|
13
|
$char_props{ $_[CONTROL] } = 0; |
826
|
|
|
|
|
|
|
|
827
|
|
|
|
|
|
|
} elsif ( $_[EVENT] eq 'start' ) { # eg. \b or \b1 |
828
|
|
|
|
|
|
|
|
829
|
9
|
|
|
|
|
40
|
$char_props{ $_[CONTROL] } = 1; |
830
|
|
|
|
|
|
|
|
831
|
|
|
|
|
|
|
} else { # 'end' |
832
|
|
|
|
|
|
|
|
833
|
0
|
|
|
|
|
0
|
warn "statement not reachable"; |
834
|
0
|
|
|
|
|
0
|
$char_props{ $_[CONTROL] } = 0; |
835
|
|
|
|
|
|
|
|
836
|
|
|
|
|
|
|
} |
837
|
|
|
|
|
|
|
|
838
|
|
|
|
|
|
|
} |
839
|
|
|
|
|
|
|
|
840
|
|
|
|
|
|
|
# LOOK MA! THIS BE IMPORTANT |
841
|
|
|
|
|
|
|
__PACKAGE__->reset_char_props(); |
842
|
|
|
|
|
|
|
__PACKAGE__->install_callback( 'char_props', 'do_on_char_prop' ); |
843
|
|
|
|
|
|
|
|
844
|
|
|
|
|
|
|
########################################################################### |
845
|
|
|
|
|
|
|
# not more used!!! |
846
|
|
|
|
|
|
|
#use constant DO_ON_TOGGLE => 0; |
847
|
|
|
|
|
|
|
#sub do_on_toggle { # associated callback |
848
|
|
|
|
|
|
|
## |
849
|
|
|
|
|
|
|
# |
850
|
|
|
|
|
|
|
# return if $IN_STYLESHEET or $IN_FONTTBL; |
851
|
|
|
|
|
|
|
# my($control, $arg, $cevent) = ($_[CONTROL], $_[ARG], $_[EVENT]); |
852
|
|
|
|
|
|
|
# trace "my(\$control, \$arg, \$cevent) = ($_[CONTROL], $_[ARG], $_[EVENT]);" if DO_ON_TOGGLE; |
853
|
|
|
|
|
|
|
# |
854
|
|
|
|
|
|
|
# if ($_[ARG] eq "0") { # \b0, register an START event for this control |
855
|
|
|
|
|
|
|
# $control[TOP]->{"$_[CONTROL]1"} = 1; # register a start event for this properties |
856
|
|
|
|
|
|
|
# $cevent = 'end'; |
857
|
|
|
|
|
|
|
# } elsif ($_[EVENT] eq 'start') { # \b or \b1 |
858
|
|
|
|
|
|
|
# $control[TOP]->{"$_[CONTROL]$_[ARG]"} = 1; |
859
|
|
|
|
|
|
|
# } else { # $_[EVENT] eq 'end' |
860
|
|
|
|
|
|
|
# if ($_[ARG] eq "1") { |
861
|
|
|
|
|
|
|
# $cevent = 'start'; |
862
|
|
|
|
|
|
|
# } else { |
863
|
|
|
|
|
|
|
# } |
864
|
|
|
|
|
|
|
# } |
865
|
|
|
|
|
|
|
# trace "(\$style, \$event, \$text) = ($control, $cevent, '')" if DO_ON_TOGGLE; |
866
|
|
|
|
|
|
|
# if (defined (my $action = $do_on_event{$control})) { |
867
|
|
|
|
|
|
|
# ($style, $event, $text) = ($control, $cevent, ''); |
868
|
|
|
|
|
|
|
# &$action; |
869
|
|
|
|
|
|
|
# } |
870
|
|
|
|
|
|
|
#} |
871
|
|
|
|
|
|
|
|
872
|
|
|
|
|
|
|
########################################################################### |
873
|
|
|
|
|
|
|
# FLAGS |
874
|
8
|
|
|
8
|
|
42
|
use constant DO_ON_FLAG => 0; |
|
8
|
|
|
|
|
13
|
|
|
8
|
|
|
|
|
1074
|
|
875
|
|
|
|
|
|
|
|
876
|
|
|
|
|
|
|
# Simply sets that pargraph properties of said flag to 1 |
877
|
|
|
|
|
|
|
|
878
|
|
|
|
|
|
|
sub do_on_flag { |
879
|
|
|
|
|
|
|
|
880
|
|
|
|
|
|
|
#my($control, $arg, $cevent) = ($_[CONTROL], $_[ARG], $_[EVENT]); |
881
|
0
|
0
|
|
0
|
0
|
0
|
die if $_[ARG]; # no argument by definition |
882
|
0
|
|
|
|
|
0
|
trace "$_[CONTROL]" if DO_ON_FLAG; |
883
|
0
|
|
|
|
|
0
|
$par_props{ $_[CONTROL] } = 1; |
884
|
|
|
|
|
|
|
|
885
|
|
|
|
|
|
|
} |
886
|
|
|
|
|
|
|
|
887
|
8
|
|
|
8
|
|
41
|
use vars qw/%charset/; |
|
8
|
|
|
|
|
14
|
|
|
8
|
|
|
|
|
697
|
|
888
|
|
|
|
|
|
|
my $bullet_item = 'b7'; # will be redefined in a next release!!! |
889
|
|
|
|
|
|
|
|
890
|
|
|
|
|
|
|
# Try to find a "RTF//char_map" file |
891
|
|
|
|
|
|
|
# possible values for the control word are: ansi, mac, pc, pca |
892
|
|
|
|
|
|
|
sub define_charset { |
893
|
|
|
|
|
|
|
|
894
|
0
|
|
|
0
|
0
|
0
|
my $charset = $_[CONTROL]; |
895
|
0
|
|
|
|
|
0
|
eval { |
896
|
8
|
|
|
8
|
|
39
|
no strict 'refs'; |
|
8
|
|
|
|
|
14
|
|
|
8
|
|
|
|
|
3522
|
|
897
|
0
|
|
|
|
|
0
|
*charset = \%{"$charset"}; |
|
0
|
|
|
|
|
0
|
|
898
|
|
|
|
|
|
|
}; |
899
|
|
|
|
|
|
|
|
900
|
0
|
0
|
|
|
|
0
|
warn $@ if $@; |
901
|
|
|
|
|
|
|
|
902
|
0
|
|
|
|
|
0
|
my @charset_data = $_[SELF]->charmap_reader('char_map'); |
903
|
|
|
|
|
|
|
|
904
|
0
|
|
|
|
|
0
|
my ( $name, $char, $hexa ); |
905
|
0
|
|
|
|
|
0
|
my %char = map { |
906
|
|
|
|
|
|
|
|
907
|
0
|
|
|
|
|
0
|
s/^\s+//; |
908
|
0
|
0
|
|
|
|
0
|
next unless /\S/; |
909
|
0
|
|
|
|
|
0
|
( $name, $char ) = split /\s+/; |
910
|
|
|
|
|
|
|
|
911
|
0
|
0
|
|
|
|
0
|
if ( !defined( $hexa = $charset{$name} ) ) { |
912
|
|
|
|
|
|
|
|
913
|
0
|
|
|
|
|
0
|
'undef' => undef; |
914
|
|
|
|
|
|
|
|
915
|
|
|
|
|
|
|
} else { |
916
|
|
|
|
|
|
|
|
917
|
0
|
|
|
|
|
0
|
$hexa => $char; |
918
|
|
|
|
|
|
|
|
919
|
|
|
|
|
|
|
} |
920
|
|
|
|
|
|
|
|
921
|
|
|
|
|
|
|
} (@charset_data); |
922
|
|
|
|
|
|
|
|
923
|
0
|
|
|
|
|
0
|
%charset = %char; # for a direct translation of hexadecimal values |
924
|
0
|
0
|
|
|
|
0
|
warn $@ if $@; |
925
|
|
|
|
|
|
|
|
926
|
|
|
|
|
|
|
} |
927
|
|
|
|
|
|
|
|
928
|
|
|
|
|
|
|
my %flag_ctrl = ( |
929
|
|
|
|
|
|
|
'ql' => \&do_on_flag, |
930
|
|
|
|
|
|
|
'qr' => \&do_on_flag, |
931
|
|
|
|
|
|
|
'qc' => \&do_on_flag, |
932
|
|
|
|
|
|
|
'qj' => \&do_on_flag, |
933
|
|
|
|
|
|
|
|
934
|
|
|
|
|
|
|
# |
935
|
|
|
|
|
|
|
'ansi' => \&define_charset, # The default |
936
|
|
|
|
|
|
|
'mac' => \&define_charset, # Apple Macintosh |
937
|
|
|
|
|
|
|
'pc' => \&define_charset, # IBM PC code page 437 |
938
|
|
|
|
|
|
|
'pca' => \&define_charset, # IBM PC code page 850 |
939
|
|
|
|
|
|
|
# |
940
|
|
|
|
|
|
|
|
941
|
|
|
|
|
|
|
'pict' => \&discard_content, # |
942
|
|
|
|
|
|
|
'xe' => \&discard_content, # index entry |
943
|
|
|
|
|
|
|
#'v' => \&discard_content, # hidden text |
944
|
|
|
|
|
|
|
); |
945
|
|
|
|
|
|
|
|
946
|
|
|
|
|
|
|
sub do_on_destination { |
947
|
0
|
|
|
0
|
0
|
0
|
trace "currently do nothing"; |
948
|
|
|
|
|
|
|
} |
949
|
|
|
|
|
|
|
my %destination_ctrl = (); |
950
|
|
|
|
|
|
|
|
951
|
|
|
|
|
|
|
sub do_on_value { |
952
|
0
|
|
|
0
|
0
|
0
|
trace "currently do nothing"; |
953
|
|
|
|
|
|
|
} |
954
|
|
|
|
|
|
|
my %value_ctrl = (); |
955
|
|
|
|
|
|
|
|
956
|
|
|
|
|
|
|
my %pn = (); # paragraph numbering |
957
|
|
|
|
|
|
|
my $field_ref = ''; # identifier associated to a field |
958
|
|
|
|
|
|
|
#trace "define callback for $_[CONTROL]"; |
959
|
|
|
|
|
|
|
|
960
|
|
|
|
|
|
|
# BEGIN API REDEFINITION |
961
|
|
|
|
|
|
|
|
962
|
|
|
|
|
|
|
# Ok, so this is actually the place to start as far as concerns |
963
|
|
|
|
|
|
|
# working out how the hell^Wfuck this thing works. I'm moving |
964
|
|
|
|
|
|
|
# all the constants to the top, and adding API documentation |
965
|
|
|
|
|
|
|
# here so future readers will have less trouble. |
966
|
|
|
|
|
|
|
|
967
|
8
|
|
|
8
|
|
47
|
use constant GROUP_START_TRACE => 0; |
|
8
|
|
|
|
|
19
|
|
|
8
|
|
|
|
|
405
|
|
968
|
8
|
|
|
8
|
|
38
|
use constant GROUP_END_TRACE => 0; |
|
8
|
|
|
|
|
13
|
|
|
8
|
|
|
|
|
335
|
|
969
|
8
|
|
|
8
|
|
35
|
use constant TEXT_TRACE => 0; |
|
8
|
|
|
|
|
12
|
|
|
8
|
|
|
|
|
329
|
|
970
|
8
|
|
|
8
|
|
43
|
use constant PARSE_START_END => 0; |
|
8
|
|
|
|
|
12
|
|
|
8
|
|
|
|
|
3385
|
|
971
|
|
|
|
|
|
|
|
972
|
|
|
|
|
|
|
# Called when we first start actually parsing the document |
973
|
|
|
|
|
|
|
sub parse_start { |
974
|
|
|
|
|
|
|
|
975
|
9
|
|
|
9
|
1
|
14
|
my $self = shift; |
976
|
|
|
|
|
|
|
|
977
|
|
|
|
|
|
|
# Place holders for non-printed data |
978
|
|
|
|
|
|
|
|
979
|
9
|
|
|
|
|
20
|
%info = (); |
980
|
9
|
|
|
|
|
22
|
%fonttbl = (); |
981
|
9
|
|
|
|
|
14
|
%colortbl = (); |
982
|
9
|
|
|
|
|
15
|
%stylesheet = (); |
983
|
|
|
|
|
|
|
|
984
|
|
|
|
|
|
|
# Add an initial element to our output stack |
985
|
|
|
|
|
|
|
|
986
|
9
|
|
|
|
|
26
|
push_output(); |
987
|
|
|
|
|
|
|
|
988
|
|
|
|
|
|
|
# If there's an event defined for the start of a document, |
989
|
|
|
|
|
|
|
# execute it now... |
990
|
|
|
|
|
|
|
|
991
|
9
|
50
|
|
|
|
37
|
if ( defined( my $action = $do_on_event{'document'} ) ) { |
992
|
|
|
|
|
|
|
|
993
|
|
|
|
|
|
|
# $event tells our action handler what's happening... |
994
|
|
|
|
|
|
|
|
995
|
9
|
|
|
|
|
17
|
$event = 'start'; |
996
|
|
|
|
|
|
|
|
997
|
|
|
|
|
|
|
# Actually execute said action |
998
|
|
|
|
|
|
|
|
999
|
9
|
|
|
|
|
28
|
&$action; |
1000
|
|
|
|
|
|
|
|
1001
|
|
|
|
|
|
|
} |
1002
|
|
|
|
|
|
|
|
1003
|
|
|
|
|
|
|
# Prints and clears the top element on the output stack |
1004
|
|
|
|
|
|
|
|
1005
|
9
|
|
|
|
|
21
|
flush_top_output(); |
1006
|
|
|
|
|
|
|
|
1007
|
|
|
|
|
|
|
# Add another element to the output stack |
1008
|
|
|
|
|
|
|
|
1009
|
9
|
|
|
|
|
18
|
push_output(); |
1010
|
|
|
|
|
|
|
|
1011
|
|
|
|
|
|
|
} |
1012
|
|
|
|
|
|
|
|
1013
|
|
|
|
|
|
|
# Called at the end of parsing |
1014
|
|
|
|
|
|
|
sub parse_end { |
1015
|
|
|
|
|
|
|
|
1016
|
9
|
|
|
9
|
1
|
21
|
my $self = shift; |
1017
|
|
|
|
|
|
|
|
1018
|
|
|
|
|
|
|
# @output_stack+0 forces scalar context? |
1019
|
9
|
|
|
|
|
12
|
trace "parseEnd \@output_stack: ", @output_stack + 0 if STACK_TRACE; |
1020
|
|
|
|
|
|
|
|
1021
|
|
|
|
|
|
|
# Call the end of document even if it exists |
1022
|
9
|
50
|
|
|
|
29
|
if ( defined( my $action = $do_on_event{'document'} ) ) { |
1023
|
|
|
|
|
|
|
|
1024
|
9
|
|
|
|
|
26
|
( $style, $event, $text ) = ( $cstylename, 'end', '' ); |
1025
|
9
|
|
|
|
|
26
|
&$action; |
1026
|
|
|
|
|
|
|
|
1027
|
|
|
|
|
|
|
} |
1028
|
|
|
|
|
|
|
|
1029
|
|
|
|
|
|
|
# Print and clear the top element on the output stack |
1030
|
|
|
|
|
|
|
|
1031
|
9
|
|
|
|
|
17
|
flush_top_output(); # @output_stack == 2; |
1032
|
|
|
|
|
|
|
|
1033
|
|
|
|
|
|
|
} |
1034
|
|
|
|
|
|
|
|
1035
|
|
|
|
|
|
|
sub group_start { # on { |
1036
|
|
|
|
|
|
|
|
1037
|
16
|
|
|
16
|
1
|
23
|
my $self = shift; |
1038
|
|
|
|
|
|
|
|
1039
|
16
|
|
|
|
|
20
|
trace "" if GROUP_START_TRACE; |
1040
|
|
|
|
|
|
|
|
1041
|
|
|
|
|
|
|
# Take a copy of the parent block's paragraph properties |
1042
|
16
|
|
|
|
|
63
|
push @par_props_stack, {%par_props}; |
1043
|
|
|
|
|
|
|
|
1044
|
|
|
|
|
|
|
# Take a copy of the parent block's character properties |
1045
|
16
|
|
|
|
|
97
|
push @char_props_stack, {%char_props}; |
1046
|
|
|
|
|
|
|
|
1047
|
|
|
|
|
|
|
# Aha! More accurately, controls we've opened, so we can close them in group_end() |
1048
|
16
|
|
|
|
|
58
|
push @control, {}; # hash of controls |
1049
|
|
|
|
|
|
|
|
1050
|
|
|
|
|
|
|
} |
1051
|
|
|
|
|
|
|
|
1052
|
|
|
|
|
|
|
sub group_end { # on } |
1053
|
|
|
|
|
|
|
# par properties |
1054
|
|
|
|
|
|
|
|
1055
|
|
|
|
|
|
|
# Retrieve parent block's paragraph properties |
1056
|
16
|
|
|
16
|
1
|
30
|
%par_props = %{ pop @par_props_stack }; |
|
16
|
|
|
|
|
52
|
|
1057
|
|
|
|
|
|
|
|
1058
|
|
|
|
|
|
|
# And use it to set the current stylename |
1059
|
16
|
|
|
|
|
235
|
$cstylename = $par_props{'stylename'}; # the current style |
1060
|
|
|
|
|
|
|
|
1061
|
|
|
|
|
|
|
# Char properties |
1062
|
|
|
|
|
|
|
# process control like \b0 |
1063
|
|
|
|
|
|
|
|
1064
|
|
|
|
|
|
|
# Grab the character properties of our parent |
1065
|
16
|
|
|
|
|
21
|
%char_props = %{ pop @char_props_stack }; |
|
16
|
|
|
|
|
118
|
|
1066
|
|
|
|
|
|
|
|
1067
|
|
|
|
|
|
|
# Fire off the 'char props have changed' event |
1068
|
16
|
|
|
|
|
47
|
$char_prop_change = 1; |
1069
|
16
|
|
|
|
|
48
|
output process_char_props(); |
1070
|
|
|
|
|
|
|
|
1071
|
|
|
|
|
|
|
# Always a /really/ /really/ bad sign :-( |
1072
|
8
|
|
|
8
|
|
54
|
no strict qw/refs/; |
|
8
|
|
|
|
|
14
|
|
|
8
|
|
|
|
|
9853
|
|
1073
|
|
|
|
|
|
|
|
1074
|
|
|
|
|
|
|
# Send an end thingy to each control we're closing |
1075
|
16
|
|
|
|
|
30
|
foreach my $control ( keys %{ pop @control } ) { # End Events! |
|
16
|
|
|
|
|
68
|
|
1076
|
9
|
|
|
|
|
28
|
$control =~ /([^\d]+)(\d+)?/; # eg: b0, b1 |
1077
|
9
|
|
|
|
|
10
|
trace "($#control): $1-$2" if GROUP_END_TRACE; |
1078
|
|
|
|
|
|
|
# sub associated to $1 is already defined in the "Action" package |
1079
|
9
|
|
|
|
|
13
|
&{"RTF::Action::$1"}( $_[SELF], $1, $2, 'end' ); |
|
9
|
|
|
|
|
36
|
|
1080
|
|
|
|
|
|
|
} |
1081
|
|
|
|
|
|
|
} |
1082
|
|
|
|
|
|
|
|
1083
|
|
|
|
|
|
|
# Just dump text |
1084
|
|
|
|
|
|
|
sub text { |
1085
|
|
|
|
|
|
|
|
1086
|
5
|
|
|
5
|
1
|
4
|
trace "$_[1]" if TEXT_TRACE; |
1087
|
5
|
|
|
|
|
15
|
output( $_[1] ); |
1088
|
|
|
|
|
|
|
|
1089
|
|
|
|
|
|
|
} |
1090
|
|
|
|
|
|
|
|
1091
|
|
|
|
|
|
|
# If we have an equiv, print it, otherwise, print the original |
1092
|
|
|
|
|
|
|
|
1093
|
|
|
|
|
|
|
sub char { |
1094
|
|
|
|
|
|
|
|
1095
|
0
|
0
|
|
0
|
1
|
0
|
if ( defined( my $char = $charset{ $_[1] } ) ) { |
1096
|
|
|
|
|
|
|
#print STDERR "$_[1] => $char\n"; |
1097
|
0
|
|
|
|
|
0
|
output "$char"; |
1098
|
|
|
|
|
|
|
} else { |
1099
|
0
|
|
|
|
|
0
|
output "$_[1]"; |
1100
|
|
|
|
|
|
|
} |
1101
|
|
|
|
|
|
|
} |
1102
|
|
|
|
|
|
|
|
1103
|
|
|
|
|
|
|
sub symbol { # symbols: \ - _ ~ : | { } * \' |
1104
|
|
|
|
|
|
|
|
1105
|
0
|
0
|
|
0
|
1
|
0
|
if ( defined( my $sym = $symbol{ $_[1] } ) ) { |
1106
|
0
|
|
|
|
|
0
|
output "$sym"; |
1107
|
|
|
|
|
|
|
} else { |
1108
|
0
|
|
|
|
|
0
|
output "$_[1]"; # as it |
1109
|
|
|
|
|
|
|
} |
1110
|
|
|
|
|
|
|
} |
1111
|
|
|
|
|
|
|
|
1112
|
|
|
|
|
|
|
sub debug { |
1113
|
|
|
|
|
|
|
|
1114
|
0
|
|
|
0
|
0
|
0
|
my $function = shift; |
1115
|
|
|
|
|
|
|
|
1116
|
0
|
|
|
|
|
0
|
print STDERR "[RTF::Control::$function]" . ( join '|', @_ ), "\n"; |
1117
|
|
|
|
|
|
|
|
1118
|
|
|
|
|
|
|
} |
1119
|
|
|
|
|
|
|
|
1120
|
|
|
|
|
|
|
%do_on_control = ( |
1121
|
|
|
|
|
|
|
%do_on_control, |
1122
|
|
|
|
|
|
|
%flag_ctrl, |
1123
|
|
|
|
|
|
|
%value_ctrl, |
1124
|
|
|
|
|
|
|
%symbol_ctrl, |
1125
|
|
|
|
|
|
|
%destination_ctrl, |
1126
|
|
|
|
|
|
|
|
1127
|
|
|
|
|
|
|
# Resets character formatting in scope... Note how we don't |
1128
|
|
|
|
|
|
|
# check for start and end events? My guess is this is because |
1129
|
|
|
|
|
|
|
# the original author is a BAD BAD MAN, and because running |
1130
|
|
|
|
|
|
|
# reset_char_props() when \plain goes out of scope doesn't |
1131
|
|
|
|
|
|
|
# cause any side effects. Something to experiment with when |
1132
|
|
|
|
|
|
|
# I have a regression test suite... |
1133
|
|
|
|
|
|
|
########################################################### |
1134
|
|
|
|
|
|
|
|
1135
|
|
|
|
|
|
|
'plain' => sub { |
1136
|
|
|
|
|
|
|
|
1137
|
|
|
|
|
|
|
reset_char_props(); |
1138
|
|
|
|
|
|
|
|
1139
|
|
|
|
|
|
|
}, |
1140
|
|
|
|
|
|
|
|
1141
|
|
|
|
|
|
|
########################################################### |
1142
|
|
|
|
|
|
|
|
1143
|
|
|
|
|
|
|
# The only thing puzzling me here is why we're doing a null |
1144
|
|
|
|
|
|
|
# call to push_output. This (and other subroutines below) |
1145
|
|
|
|
|
|
|
# are ripe for a bit of refactoring - they all do the same |
1146
|
|
|
|
|
|
|
# thing! |
1147
|
|
|
|
|
|
|
########################################################### |
1148
|
|
|
|
|
|
|
|
1149
|
|
|
|
|
|
|
'rtf' => sub { # rtfN, N is version number |
1150
|
|
|
|
|
|
|
|
1151
|
6
|
100
|
|
2
|
|
19
|
if ( $_[EVENT] eq 'start' ) { |
1152
|
|
|
|
|
|
|
|
1153
|
3
|
|
|
|
|
7
|
push_output('nul'); |
1154
|
3
|
|
|
|
|
12
|
$control[TOP]->{"$_[CONTROL]$_[ARG]"} = 1; |
1155
|
|
|
|
|
|
|
|
1156
|
|
|
|
|
|
|
} else { |
1157
|
|
|
|
|
|
|
|
1158
|
|
|
|
|
|
|
# There may actually be content at this point! |
1159
|
3
|
|
|
|
|
10
|
flush_top_output(); |
1160
|
|
|
|
|
|
|
|
1161
|
|
|
|
|
|
|
# The buffer should be empty at this point. |
1162
|
|
|
|
|
|
|
# Make it so :-) This should use an RTF::Tokenizer |
1163
|
|
|
|
|
|
|
# method before I release this as production. |
1164
|
|
|
|
|
|
|
# TODO... |
1165
|
|
|
|
|
|
|
|
1166
|
3
|
|
|
|
|
9
|
$_[SELF]->{_TOKENIZER}->{_BUFFER} = ''; |
1167
|
3
|
|
|
|
|
21
|
$_[SELF]->{_TOKENIZER}->{_FILEHANDLE} = ''; |
1168
|
|
|
|
|
|
|
|
1169
|
|
|
|
|
|
|
} |
1170
|
|
|
|
|
|
|
|
1171
|
|
|
|
|
|
|
}, |
1172
|
|
|
|
|
|
|
|
1173
|
|
|
|
|
|
|
########################################################### |
1174
|
|
|
|
|
|
|
|
1175
|
|
|
|
|
|
|
# Info group. The &do_on_info sub is trivial, and merely puts |
1176
|
|
|
|
|
|
|
# the rest of the text in a destination into %info, with the |
1177
|
|
|
|
|
|
|
# key being the field (like 'title'). creatim is kinda clever |
1178
|
|
|
|
|
|
|
# then in that it turns the rest of those fields into one |
1179
|
|
|
|
|
|
|
# long text string. |
1180
|
|
|
|
|
|
|
# |
1181
|
|
|
|
|
|
|
# Other information we could grab: |
1182
|
|
|
|
|
|
|
# {\printim\yr1997\mo11\dy3\hr11\min5} |
1183
|
|
|
|
|
|
|
# {\version3}{\edmins1}{\nofpages3}{\nofwords1278}{\nofchars7287} |
1184
|
|
|
|
|
|
|
# {\*\company SONOVISION-ITEP}{\vern57443} |
1185
|
|
|
|
|
|
|
########################################################### |
1186
|
|
|
|
|
|
|
|
1187
|
|
|
|
|
|
|
'info' => sub { # {\info {...}} |
1188
|
|
|
|
|
|
|
|
1189
|
|
|
|
|
|
|
if ( $_[EVENT] eq 'start' ) { |
1190
|
|
|
|
|
|
|
|
1191
|
|
|
|
|
|
|
# Stops us collecting any text we don't want |
1192
|
|
|
|
|
|
|
|
1193
|
|
|
|
|
|
|
push_output('nul'); |
1194
|
|
|
|
|
|
|
$control[TOP]->{"$_[CONTROL]$_[ARG]"} = 1; |
1195
|
|
|
|
|
|
|
|
1196
|
|
|
|
|
|
|
} else { |
1197
|
|
|
|
|
|
|
|
1198
|
|
|
|
|
|
|
pop_output(); |
1199
|
|
|
|
|
|
|
|
1200
|
|
|
|
|
|
|
} |
1201
|
|
|
|
|
|
|
|
1202
|
|
|
|
|
|
|
}, |
1203
|
|
|
|
|
|
|
|
1204
|
|
|
|
|
|
|
'title' => \&do_on_info, # destination |
1205
|
|
|
|
|
|
|
'author' => \&do_on_info, # destination |
1206
|
|
|
|
|
|
|
'revtim' => \&do_on_info, # destination |
1207
|
|
|
|
|
|
|
'creatim' => |
1208
|
|
|
|
|
|
|
\&do_on_info, # destination, {\creatim\yr1996\mo9\dy18\hr9\min17} |
1209
|
|
|
|
|
|
|
'yr' => sub { output "$_[ARG]-" }, # value |
1210
|
|
|
|
|
|
|
'mo' => sub { output "$_[ARG]-" }, # value |
1211
|
|
|
|
|
|
|
'dy' => sub { output "$_[ARG]-" }, # value |
1212
|
|
|
|
|
|
|
'hr' => sub { output "$_[ARG]-" }, # value |
1213
|
|
|
|
|
|
|
'min' => sub { output "$_[ARG]" }, # value |
1214
|
|
|
|
|
|
|
|
1215
|
|
|
|
|
|
|
########################################################### |
1216
|
|
|
|
|
|
|
|
1217
|
|
|
|
|
|
|
# Read binary data - only, this function has been removed |
1218
|
|
|
|
|
|
|
# from RTF::Parser.pm. Ooops. Add it back in and PUT IN |
1219
|
|
|
|
|
|
|
# A TEST. |
1220
|
|
|
|
|
|
|
########################################################### |
1221
|
|
|
|
|
|
|
|
1222
|
|
|
|
|
|
|
'bin' => sub { $_[SELF]->read_bin( $_[ARG] ) }, # value |
1223
|
|
|
|
|
|
|
|
1224
|
|
|
|
|
|
|
# \ulnone should be treated as if it were \ul0... |
1225
|
|
|
|
|
|
|
########################################################### |
1226
|
|
|
|
|
|
|
|
1227
|
|
|
|
|
|
|
'ulnone' => sub { |
1228
|
|
|
|
|
|
|
|
1229
|
|
|
|
|
|
|
$_[SELF]->do_on_char_prop( 'ul', '0', 'start' ); |
1230
|
|
|
|
|
|
|
|
1231
|
|
|
|
|
|
|
}, |
1232
|
|
|
|
|
|
|
|
1233
|
|
|
|
|
|
|
# Clearly we're not interested in the colour table.... |
1234
|
|
|
|
|
|
|
########################################################### |
1235
|
|
|
|
|
|
|
|
1236
|
|
|
|
|
|
|
'colortbl' => \&discard_content, |
1237
|
|
|
|
|
|
|
|
1238
|
|
|
|
|
|
|
# The start of the font-table. There's a global(ish) flag |
1239
|
|
|
|
|
|
|
# $IN_FONTTBL that influences how other parts of the module |
1240
|
|
|
|
|
|
|
# work. The main thing we do is turn this flag on when we |
1241
|
|
|
|
|
|
|
# get to this point. The 'push_output('nul')' also turns |
1242
|
|
|
|
|
|
|
# off any output while we're in the font table. |
1243
|
|
|
|
|
|
|
########################################################### |
1244
|
|
|
|
|
|
|
|
1245
|
|
|
|
|
|
|
'fonttbl' => sub { |
1246
|
|
|
|
|
|
|
|
1247
|
3
|
50
|
|
|
|
5
|
if ( $_[EVENT] eq 'start' ) { |
1248
|
|
|
|
|
|
|
|
1249
|
|
|
|
|
|
|
# Set the global flag |
1250
|
3
|
|
|
|
|
10
|
$IN_FONTTBL = 1; |
1251
|
|
|
|
|
|
|
|
1252
|
|
|
|
|
|
|
# Turn off output |
1253
|
0
|
|
|
|
|
0
|
push_output('nul'); |
1254
|
|
|
|
|
|
|
|
1255
|
|
|
|
|
|
|
# Remember that this event has fired, and close it |
1256
|
|
|
|
|
|
|
# when we go out of scope. |
1257
|
6
|
|
|
|
|
25
|
$control[TOP]->{"$_[CONTROL]$_[ARG]"} = 1; |
1258
|
|
|
|
|
|
|
|
1259
|
|
|
|
|
|
|
} else { |
1260
|
|
|
|
|
|
|
|
1261
|
0
|
|
|
|
|
0
|
$IN_FONTTBL = 0; |
1262
|
0
|
|
|
|
|
0
|
pop_output(); |
1263
|
|
|
|
|
|
|
|
1264
|
|
|
|
|
|
|
} |
1265
|
|
|
|
|
|
|
|
1266
|
|
|
|
|
|
|
}, |
1267
|
|
|
|
|
|
|
|
1268
|
|
|
|
|
|
|
########################################################### |
1269
|
|
|
|
|
|
|
|
1270
|
|
|
|
|
|
|
# We seem to not want anything to do with the filetable |
1271
|
|
|
|
|
|
|
# either - I guess the reason we define a control for it |
1272
|
|
|
|
|
|
|
# (because otherwise it'd get skipped as an unknow destination |
1273
|
|
|
|
|
|
|
# I think) is so that subclassers can handle it if they |
1274
|
|
|
|
|
|
|
# want. |
1275
|
|
|
|
|
|
|
########################################################### |
1276
|
|
|
|
|
|
|
|
1277
|
|
|
|
|
|
|
'filetbl' => sub { |
1278
|
|
|
|
|
|
|
|
1279
|
|
|
|
|
|
|
#trace "$#control $_[CONTROL] $_[ARG] $_[EVENT]"; |
1280
|
|
|
|
|
|
|
if ( $_[EVENT] eq 'start' ) { |
1281
|
|
|
|
|
|
|
|
1282
|
|
|
|
|
|
|
push_output('nul'); |
1283
|
|
|
|
|
|
|
$control[TOP]->{"$_[CONTROL]$_[ARG]"} = 1; |
1284
|
|
|
|
|
|
|
|
1285
|
|
|
|
|
|
|
} else { |
1286
|
|
|
|
|
|
|
|
1287
|
|
|
|
|
|
|
pop_output(); |
1288
|
|
|
|
|
|
|
|
1289
|
|
|
|
|
|
|
} |
1290
|
|
|
|
|
|
|
|
1291
|
|
|
|
|
|
|
}, |
1292
|
|
|
|
|
|
|
|
1293
|
|
|
|
|
|
|
########################################################### |
1294
|
|
|
|
|
|
|
|
1295
|
|
|
|
|
|
|
# A font control - highly context-dependant control word ... Can be used |
1296
|
|
|
|
|
|
|
# to introduce a font definition when we're in the font-table, to specify |
1297
|
|
|
|
|
|
|
# which font a style uses in the style-table, or to change the font we're |
1298
|
|
|
|
|
|
|
# currently using when used as a paragraph/character property. |
1299
|
|
|
|
|
|
|
########################################################### |
1300
|
|
|
|
|
|
|
|
1301
|
|
|
|
|
|
|
'f' => sub { |
1302
|
|
|
|
|
|
|
|
1303
|
8
|
|
|
|
|
10459
|
use constant FONTTBL_TRACE => |
1304
|
8
|
|
|
8
|
|
42
|
0; # if you want to see the fonttbl of the document |
|
8
|
|
|
|
|
16
|
|
1305
|
|
|
|
|
|
|
|
1306
|
|
|
|
|
|
|
# We're in the middle of the font-table, so this is a font definition. |
1307
|
|
|
|
|
|
|
# We're only really interested in what happens when we pass *out* of |
1308
|
|
|
|
|
|
|
# scope, because at that point we'll have grabbed the font-name. I'd |
1309
|
|
|
|
|
|
|
# like to add panose support at some point. |
1310
|
|
|
|
|
|
|
|
1311
|
0
|
50
|
|
|
|
0
|
if ($IN_FONTTBL) { |
|
|
50
|
|
|
|
|
|
1312
|
|
|
|
|
|
|
|
1313
|
0
|
0
|
|
|
|
0
|
if ( $_[EVENT] eq 'start' ) { |
1314
|
|
|
|
|
|
|
|
1315
|
|
|
|
|
|
|
# Add a new element to the output stack that we can |
1316
|
|
|
|
|
|
|
# snarf back in a minute when we hit the group close |
1317
|
|
|
|
|
|
|
|
1318
|
0
|
|
|
|
|
0
|
push_output(); |
1319
|
|
|
|
|
|
|
|
1320
|
|
|
|
|
|
|
# Say we're open |
1321
|
|
|
|
|
|
|
|
1322
|
0
|
|
|
|
|
0
|
$control[TOP]->{"$_[CONTROL]$_[ARG]"} = 1; |
1323
|
|
|
|
|
|
|
|
1324
|
|
|
|
|
|
|
} else { |
1325
|
|
|
|
|
|
|
|
1326
|
|
|
|
|
|
|
# Grab the element from the output stack, which'll be |
1327
|
|
|
|
|
|
|
# our fontname |
1328
|
|
|
|
|
|
|
|
1329
|
0
|
|
|
|
|
0
|
my $fontname = pop_output; |
1330
|
|
|
|
|
|
|
|
1331
|
|
|
|
|
|
|
# This will be something like 'f1' |
1332
|
|
|
|
|
|
|
|
1333
|
0
|
|
|
|
|
0
|
my $fontdef = "$_[CONTROL]$_[ARG]"; |
1334
|
|
|
|
|
|
|
|
1335
|
|
|
|
|
|
|
# Remove the trailing semi-colon and any space |
1336
|
|
|
|
|
|
|
|
1337
|
0
|
100
|
|
|
|
0
|
if ( $fontname =~ s/\s*;$// ) { |
1338
|
|
|
|
|
|
|
|
1339
|
0
|
|
|
|
|
0
|
trace "$fontdef => $fontname" if FONTTBL_TRACE; |
1340
|
|
|
|
|
|
|
|
1341
|
|
|
|
|
|
|
# Set the fontdef and the fontname in the font-table hash |
1342
|
|
|
|
|
|
|
|
1343
|
0
|
|
|
|
|
0
|
$fonttbl{$fontdef} = $fontname; |
1344
|
|
|
|
|
|
|
|
1345
|
|
|
|
|
|
|
} else { |
1346
|
|
|
|
|
|
|
|
1347
|
0
|
|
|
|
|
0
|
warn "can't analyze $fontname"; |
1348
|
|
|
|
|
|
|
|
1349
|
|
|
|
|
|
|
} |
1350
|
|
|
|
|
|
|
|
1351
|
|
|
|
|
|
|
} |
1352
|
|
|
|
|
|
|
|
1353
|
3
|
|
|
|
|
10
|
return; |
1354
|
|
|
|
|
|
|
|
1355
|
|
|
|
|
|
|
# We're in the style sheet. This part doesn't make much sense |
1356
|
|
|
|
|
|
|
# just yet, will come back to it. Looks like \f is being used |
1357
|
|
|
|
|
|
|
# to recognise when a style definition is finished?! Bizarre. |
1358
|
|
|
|
|
|
|
|
1359
|
|
|
|
|
|
|
} elsif ($IN_STYLESHEET) { # eg. \f1 => Normal; |
1360
|
|
|
|
|
|
|
|
1361
|
3
|
0
|
|
|
|
6
|
return if $styledef; # if you have already encountered an \sn |
1362
|
3
|
|
|
|
|
6
|
$styledef = "$_[CONTROL]$_[ARG]"; |
1363
|
|
|
|
|
|
|
|
1364
|
3
|
100
|
|
|
|
61
|
if ( $_[EVENT] eq 'start' ) { |
1365
|
|
|
|
|
|
|
|
1366
|
|
|
|
|
|
|
#trace "start $_[CONTROL]$_[ARG]" if STYLESHEET; |
1367
|
3
|
|
|
|
|
16
|
push_output(); |
1368
|
0
|
|
|
|
|
0
|
$control[TOP]->{"$_[CONTROL]$_[ARG]"} = 1; |
1369
|
|
|
|
|
|
|
|
1370
|
|
|
|
|
|
|
} else { |
1371
|
|
|
|
|
|
|
|
1372
|
0
|
|
|
|
|
0
|
my $stylename = pop_output; |
1373
|
|
|
|
|
|
|
#trace "end\n $_[CONTROL]" if STYLESHEET; |
1374
|
|
|
|
|
|
|
|
1375
|
0
|
0
|
|
|
|
0
|
if ( $stylename =~ s/\s*;$// ) { |
1376
|
|
|
|
|
|
|
|
1377
|
0
|
|
|
|
|
0
|
trace "$styledef => $stylename" if STYLESHEET_TRACE; |
1378
|
0
|
|
|
|
|
0
|
$stylesheet{$styledef} = $stylename; |
1379
|
|
|
|
|
|
|
|
1380
|
|
|
|
|
|
|
} else { |
1381
|
|
|
|
|
|
|
|
1382
|
0
|
|
|
|
|
0
|
warn |
1383
|
|
|
|
|
|
|
"can't analyze '$stylename' ($styledef; event: $_[EVENT])"; |
1384
|
|
|
|
|
|
|
|
1385
|
|
|
|
|
|
|
} |
1386
|
|
|
|
|
|
|
|
1387
|
|
|
|
|
|
|
} |
1388
|
|
|
|
|
|
|
|
1389
|
4
|
|
|
|
|
6
|
$styledef = ''; |
1390
|
4
|
|
|
|
|
31
|
return; |
1391
|
|
|
|
|
|
|
|
1392
|
|
|
|
|
|
|
} |
1393
|
|
|
|
|
|
|
|
1394
|
0
|
50
|
|
|
|
0
|
return if $styledef; # if you have already encountered an \sn |
1395
|
|
|
|
|
|
|
|
1396
|
|
|
|
|
|
|
# This doesn't make a great deal of sense |
1397
|
0
|
|
|
|
|
0
|
$styledef = "$_[CONTROL]$_[ARG]"; |
1398
|
0
|
|
|
|
|
0
|
$stylename = $stylesheet{"$styledef"}; |
1399
|
0
|
|
|
|
|
0
|
trace "$styledef => $stylename" if STYLESHEET_TRACE; |
1400
|
|
|
|
|
|
|
|
1401
|
0
|
0
|
|
|
|
0
|
return unless $stylename; |
1402
|
|
|
|
|
|
|
|
1403
|
0
|
0
|
|
|
|
0
|
if ( $cstylename ne $stylename ) { # notify a style changing |
1404
|
|
|
|
|
|
|
|
1405
|
0
|
0
|
|
|
|
0
|
if ( defined( my $action = $do_on_event{'style_change'} ) ) { |
1406
|
|
|
|
|
|
|
|
1407
|
0
|
|
|
|
|
0
|
( $style, $newstyle ) = ( $cstylename, $stylename ); |
1408
|
0
|
|
|
|
|
0
|
&$action; |
1409
|
|
|
|
|
|
|
|
1410
|
|
|
|
|
|
|
} |
1411
|
|
|
|
|
|
|
|
1412
|
|
|
|
|
|
|
} |
1413
|
|
|
|
|
|
|
|
1414
|
0
|
|
|
|
|
0
|
$cstylename = $stylename; |
1415
|
0
|
|
|
|
|
0
|
$par_props{'stylename'} = $cstylename; # the current style |
1416
|
|
|
|
|
|
|
|
1417
|
|
|
|
|
|
|
}, |
1418
|
|
|
|
|
|
|
|
1419
|
|
|
|
|
|
|
########################################################### |
1420
|
|
|
|
|
|
|
|
1421
|
|
|
|
|
|
|
# Stylesheet - like font-table above, we set the flag, and |
1422
|
|
|
|
|
|
|
# make sure we don't grab any unwanted text... |
1423
|
|
|
|
|
|
|
|
1424
|
|
|
|
|
|
|
'stylesheet' => sub { |
1425
|
|
|
|
|
|
|
|
1426
|
|
|
|
|
|
|
trace "stylesheet $#control $_[CONTROL] $_[ARG] $_[EVENT]" |
1427
|
|
|
|
|
|
|
if STYLESHEET_TRACE; |
1428
|
|
|
|
|
|
|
|
1429
|
|
|
|
|
|
|
if ( $_[EVENT] eq 'start' ) { |
1430
|
|
|
|
|
|
|
|
1431
|
|
|
|
|
|
|
$IN_STYLESHEET = 1; |
1432
|
|
|
|
|
|
|
push_output('nul'); |
1433
|
|
|
|
|
|
|
$control[TOP]->{"$_[CONTROL]$_[ARG]"} = 1; |
1434
|
|
|
|
|
|
|
|
1435
|
|
|
|
|
|
|
} else { |
1436
|
|
|
|
|
|
|
|
1437
|
|
|
|
|
|
|
$IN_STYLESHEET = 0; |
1438
|
|
|
|
|
|
|
pop_output; |
1439
|
|
|
|
|
|
|
|
1440
|
|
|
|
|
|
|
} |
1441
|
|
|
|
|
|
|
}, |
1442
|
|
|
|
|
|
|
|
1443
|
|
|
|
|
|
|
########################################################### |
1444
|
|
|
|
|
|
|
|
1445
|
|
|
|
|
|
|
# Stylesheet definition |
1446
|
|
|
|
|
|
|
########################################################### |
1447
|
|
|
|
|
|
|
|
1448
|
|
|
|
|
|
|
's' => sub { |
1449
|
|
|
|
|
|
|
|
1450
|
|
|
|
|
|
|
my ( $control, $arg, $cevent ) = ( $_[CONTROL], $_[ARG], $_[EVENT] ); |
1451
|
|
|
|
|
|
|
|
1452
|
|
|
|
|
|
|
$styledef = "$_[CONTROL]$_[ARG]"; |
1453
|
|
|
|
|
|
|
|
1454
|
|
|
|
|
|
|
# This looks pretty much identical to \f - only, looking at it, |
1455
|
|
|
|
|
|
|
# it probably doesn't work. My head hurts. |
1456
|
|
|
|
|
|
|
|
1457
|
|
|
|
|
|
|
if ($IN_STYLESHEET) { |
1458
|
|
|
|
|
|
|
|
1459
|
|
|
|
|
|
|
if ( $_[EVENT] eq 'start' ) { |
1460
|
|
|
|
|
|
|
|
1461
|
|
|
|
|
|
|
push_output(); |
1462
|
|
|
|
|
|
|
$control[TOP]->{"$_[CONTROL]$_[ARG]"} = 1; |
1463
|
|
|
|
|
|
|
|
1464
|
|
|
|
|
|
|
} else { |
1465
|
|
|
|
|
|
|
|
1466
|
|
|
|
|
|
|
my $stylename = pop_output; |
1467
|
|
|
|
|
|
|
warn "empty stylename" and return if $stylename eq ''; |
1468
|
|
|
|
|
|
|
|
1469
|
|
|
|
|
|
|
if ( $stylename =~ s/\s*;$// ) { |
1470
|
|
|
|
|
|
|
|
1471
|
|
|
|
|
|
|
trace "$styledef => $stylename|" if STYLESHEET_TRACE; |
1472
|
|
|
|
|
|
|
$stylesheet{$styledef} = $stylename; |
1473
|
|
|
|
|
|
|
$styledef = ''; |
1474
|
|
|
|
|
|
|
|
1475
|
|
|
|
|
|
|
} else { |
1476
|
|
|
|
|
|
|
|
1477
|
|
|
|
|
|
|
warn "can't analyze style name: '$stylename'"; |
1478
|
|
|
|
|
|
|
|
1479
|
|
|
|
|
|
|
} |
1480
|
|
|
|
|
|
|
|
1481
|
|
|
|
|
|
|
} |
1482
|
|
|
|
|
|
|
|
1483
|
|
|
|
|
|
|
return; |
1484
|
|
|
|
|
|
|
|
1485
|
|
|
|
|
|
|
} |
1486
|
|
|
|
|
|
|
|
1487
|
|
|
|
|
|
|
$stylename = $stylesheet{"$styledef"}; |
1488
|
|
|
|
|
|
|
|
1489
|
|
|
|
|
|
|
if ( $cstylename ne $stylename ) { |
1490
|
|
|
|
|
|
|
|
1491
|
|
|
|
|
|
|
if ( defined( my $action = $do_on_event{'style_change'} ) ) { |
1492
|
|
|
|
|
|
|
|
1493
|
|
|
|
|
|
|
( $style, $newstyle ) = ( $cstylename, $stylename ); |
1494
|
|
|
|
|
|
|
|
1495
|
|
|
|
|
|
|
&$action; |
1496
|
|
|
|
|
|
|
|
1497
|
|
|
|
|
|
|
} |
1498
|
|
|
|
|
|
|
|
1499
|
|
|
|
|
|
|
} |
1500
|
|
|
|
|
|
|
|
1501
|
|
|
|
|
|
|
$cstylename = $stylename; |
1502
|
|
|
|
|
|
|
$par_props{'stylename'} = $cstylename; # the current style |
1503
|
|
|
|
|
|
|
trace "$styledef => $stylename" if STYLESHEET_TRACE; |
1504
|
|
|
|
|
|
|
|
1505
|
|
|
|
|
|
|
}, |
1506
|
|
|
|
|
|
|
|
1507
|
|
|
|
|
|
|
########################################################### |
1508
|
|
|
|
|
|
|
|
1509
|
|
|
|
|
|
|
# Tells us we're starting a row... |
1510
|
|
|
|
|
|
|
########################################################### |
1511
|
|
|
|
|
|
|
|
1512
|
|
|
|
|
|
|
'trowd' => sub { |
1513
|
|
|
|
|
|
|
|
1514
|
8
|
|
|
8
|
|
48
|
use constant TABLE_TRACE => 0; |
|
8
|
|
|
|
|
18
|
|
|
8
|
|
|
|
|
18804
|
|
1515
|
|
|
|
|
|
|
|
1516
|
|
|
|
|
|
|
#print STDERR "=>Beginning of ROW\n"; |
1517
|
|
|
|
|
|
|
|
1518
|
|
|
|
|
|
|
# If we're not in a table... |
1519
|
|
|
|
|
|
|
|
1520
|
|
|
|
|
|
|
unless ($IN_TABLE) { |
1521
|
|
|
|
|
|
|
|
1522
|
|
|
|
|
|
|
# Set the flag to say we now are |
1523
|
|
|
|
|
|
|
|
1524
|
|
|
|
|
|
|
$IN_TABLE = 1; |
1525
|
|
|
|
|
|
|
|
1526
|
|
|
|
|
|
|
# Fire off a table even if we have one |
1527
|
|
|
|
|
|
|
|
1528
|
|
|
|
|
|
|
if ( defined( my $action = $do_on_event{'table'} ) ) { |
1529
|
|
|
|
|
|
|
|
1530
|
|
|
|
|
|
|
$event = 'start'; |
1531
|
|
|
|
|
|
|
trace "table $event $text\n" if TABLE_TRACE; |
1532
|
|
|
|
|
|
|
&$action; |
1533
|
|
|
|
|
|
|
|
1534
|
|
|
|
|
|
|
} |
1535
|
|
|
|
|
|
|
|
1536
|
|
|
|
|
|
|
# Add lots of output holders for various things... |
1537
|
|
|
|
|
|
|
|
1538
|
|
|
|
|
|
|
push_output(); # table content |
1539
|
|
|
|
|
|
|
push_output(); # row sequence |
1540
|
|
|
|
|
|
|
push_output(); # cell sequence |
1541
|
|
|
|
|
|
|
push_output(); # cell content |
1542
|
|
|
|
|
|
|
|
1543
|
|
|
|
|
|
|
} |
1544
|
|
|
|
|
|
|
|
1545
|
|
|
|
|
|
|
}, |
1546
|
|
|
|
|
|
|
|
1547
|
|
|
|
|
|
|
# Perhaps the control that opens a table? Never the less, |
1548
|
|
|
|
|
|
|
# an exact clone of the function above! |
1549
|
|
|
|
|
|
|
########################################################### |
1550
|
|
|
|
|
|
|
|
1551
|
|
|
|
|
|
|
'intbl' => sub { |
1552
|
|
|
|
|
|
|
|
1553
|
|
|
|
|
|
|
$par_props{'intbl'} = 1; |
1554
|
|
|
|
|
|
|
|
1555
|
|
|
|
|
|
|
unless ($IN_TABLE) { |
1556
|
|
|
|
|
|
|
|
1557
|
|
|
|
|
|
|
warn "ouverture en catastrophe" if TABLE_TRACE; |
1558
|
|
|
|
|
|
|
$IN_TABLE = 1; |
1559
|
|
|
|
|
|
|
|
1560
|
|
|
|
|
|
|
if ( defined( my $action = $do_on_event{'table'} ) ) { |
1561
|
|
|
|
|
|
|
|
1562
|
|
|
|
|
|
|
$event = 'start'; |
1563
|
|
|
|
|
|
|
trace "table $event $text\n" if TABLE_TRACE; |
1564
|
|
|
|
|
|
|
&$action; |
1565
|
|
|
|
|
|
|
|
1566
|
|
|
|
|
|
|
} |
1567
|
|
|
|
|
|
|
|
1568
|
|
|
|
|
|
|
push_output(); |
1569
|
|
|
|
|
|
|
push_output(); |
1570
|
|
|
|
|
|
|
push_output(); |
1571
|
|
|
|
|
|
|
push_output(); |
1572
|
|
|
|
|
|
|
|
1573
|
|
|
|
|
|
|
} |
1574
|
|
|
|
|
|
|
|
1575
|
|
|
|
|
|
|
}, |
1576
|
|
|
|
|
|
|
|
1577
|
|
|
|
|
|
|
# The end of a row |
1578
|
|
|
|
|
|
|
########################################################### |
1579
|
|
|
|
|
|
|
|
1580
|
|
|
|
|
|
|
'row' => sub { # row end |
1581
|
|
|
|
|
|
|
|
1582
|
|
|
|
|
|
|
# Grab the cell and the 'cell sequence' |
1583
|
|
|
|
|
|
|
|
1584
|
|
|
|
|
|
|
$text = pop_output; |
1585
|
|
|
|
|
|
|
$text = pop_output . $text; |
1586
|
|
|
|
|
|
|
|
1587
|
|
|
|
|
|
|
# Fire off the 'end cell' handler if we have one |
1588
|
|
|
|
|
|
|
|
1589
|
|
|
|
|
|
|
if ( defined( my $action = $do_on_event{'cell'} ) ) { |
1590
|
|
|
|
|
|
|
|
1591
|
|
|
|
|
|
|
$event = 'end'; |
1592
|
|
|
|
|
|
|
trace "row $event $text\n" if TABLE_TRACE; |
1593
|
|
|
|
|
|
|
&$action; |
1594
|
|
|
|
|
|
|
|
1595
|
|
|
|
|
|
|
} |
1596
|
|
|
|
|
|
|
|
1597
|
|
|
|
|
|
|
# Grab any row text |
1598
|
|
|
|
|
|
|
|
1599
|
|
|
|
|
|
|
$text = pop_output; |
1600
|
|
|
|
|
|
|
|
1601
|
|
|
|
|
|
|
# Fire off the end-row event |
1602
|
|
|
|
|
|
|
|
1603
|
|
|
|
|
|
|
if ( defined( my $action = $do_on_event{'row'} ) ) { |
1604
|
|
|
|
|
|
|
|
1605
|
|
|
|
|
|
|
$event = 'end'; |
1606
|
|
|
|
|
|
|
trace "row $event $text\n" if TABLE_TRACE; |
1607
|
|
|
|
|
|
|
&$action; |
1608
|
|
|
|
|
|
|
} |
1609
|
|
|
|
|
|
|
|
1610
|
|
|
|
|
|
|
# Prep the next row |
1611
|
|
|
|
|
|
|
|
1612
|
|
|
|
|
|
|
push_output(); |
1613
|
|
|
|
|
|
|
push_output(); |
1614
|
|
|
|
|
|
|
push_output(); |
1615
|
|
|
|
|
|
|
|
1616
|
|
|
|
|
|
|
}, |
1617
|
|
|
|
|
|
|
|
1618
|
|
|
|
|
|
|
########################################################### |
1619
|
|
|
|
|
|
|
|
1620
|
|
|
|
|
|
|
# End of a cell |
1621
|
|
|
|
|
|
|
########################################################### |
1622
|
|
|
|
|
|
|
|
1623
|
|
|
|
|
|
|
'cell' => sub { # end of cell |
1624
|
|
|
|
|
|
|
|
1625
|
|
|
|
|
|
|
trace "process cell content: $text\n" if TABLE_TRACE; |
1626
|
|
|
|
|
|
|
$text = pop_output; |
1627
|
|
|
|
|
|
|
|
1628
|
|
|
|
|
|
|
# Fire the paragraph handler |
1629
|
|
|
|
|
|
|
|
1630
|
|
|
|
|
|
|
if ( defined( my $action = $do_on_event{'par'} ) ) { |
1631
|
|
|
|
|
|
|
|
1632
|
|
|
|
|
|
|
( $style, $event, ) = ( 'par', 'end', ); |
1633
|
|
|
|
|
|
|
&$action; |
1634
|
|
|
|
|
|
|
|
1635
|
|
|
|
|
|
|
} else { |
1636
|
|
|
|
|
|
|
|
1637
|
|
|
|
|
|
|
warn "$text"; |
1638
|
|
|
|
|
|
|
|
1639
|
|
|
|
|
|
|
} |
1640
|
|
|
|
|
|
|
|
1641
|
|
|
|
|
|
|
$text = pop_output; |
1642
|
|
|
|
|
|
|
|
1643
|
|
|
|
|
|
|
# Fire the end-cell handler |
1644
|
|
|
|
|
|
|
|
1645
|
|
|
|
|
|
|
if ( defined( my $action = $do_on_event{'cell'} ) ) { |
1646
|
|
|
|
|
|
|
|
1647
|
|
|
|
|
|
|
$event = 'end'; |
1648
|
|
|
|
|
|
|
trace "cell $event $text\n" if TABLE_TRACE; |
1649
|
|
|
|
|
|
|
&$action; |
1650
|
|
|
|
|
|
|
|
1651
|
|
|
|
|
|
|
} |
1652
|
|
|
|
|
|
|
# prepare next cell |
1653
|
|
|
|
|
|
|
push_output(); |
1654
|
|
|
|
|
|
|
push_output(); |
1655
|
|
|
|
|
|
|
trace "\@output_stack in table: ", @output_stack + 0 if STACK_TRACE; |
1656
|
|
|
|
|
|
|
|
1657
|
|
|
|
|
|
|
}, |
1658
|
|
|
|
|
|
|
|
1659
|
|
|
|
|
|
|
########################################################### |
1660
|
|
|
|
|
|
|
|
1661
|
|
|
|
|
|
|
# And thus the paragraph ends |
1662
|
|
|
|
|
|
|
########################################################### |
1663
|
|
|
|
|
|
|
|
1664
|
|
|
|
|
|
|
'par' => sub { # END OF PARAGRAPH |
1665
|
|
|
|
|
|
|
|
1666
|
0
|
|
|
|
|
0
|
trace "($_[CONTROL], $_[ARG], $_[EVENT])" if STYLE_TRACE; |
1667
|
|
|
|
|
|
|
|
1668
|
|
|
|
|
|
|
# Close a table. Add to $text, and call even handlers |
1669
|
|
|
|
|
|
|
# for cell, row, and table, in order. |
1670
|
|
|
|
|
|
|
|
1671
|
0
|
50
|
33
|
|
|
0
|
if ( $IN_TABLE and not $par_props{'intbl'} ) { # End of Table |
1672
|
|
|
|
|
|
|
|
1673
|
0
|
|
|
|
|
0
|
$IN_TABLE = 0; |
1674
|
0
|
|
|
|
|
0
|
my $next_text = pop_output; # next paragraph content |
1675
|
|
|
|
|
|
|
|
1676
|
0
|
|
|
|
|
0
|
$text = pop_output; |
1677
|
0
|
|
|
|
|
0
|
$text = pop_output . "$text"; |
1678
|
|
|
|
|
|
|
|
1679
|
0
|
0
|
|
|
|
0
|
if ( defined( my $action = $do_on_event{'cell'} ) ) { # end of cell |
1680
|
|
|
|
|
|
|
|
1681
|
0
|
|
|
|
|
0
|
$event = 'end'; |
1682
|
0
|
|
|
|
|
0
|
trace "cell $event $text\n" if TABLE_TRACE; |
1683
|
0
|
|
|
|
|
0
|
&$action; |
1684
|
|
|
|
|
|
|
|
1685
|
|
|
|
|
|
|
} |
1686
|
|
|
|
|
|
|
|
1687
|
4
|
|
|
|
|
26
|
$text = pop_output; |
1688
|
|
|
|
|
|
|
|
1689
|
0
|
0
|
|
|
|
0
|
if ( defined( my $action = $do_on_event{'row'} ) ) { # end of row |
1690
|
|
|
|
|
|
|
|
1691
|
4
|
|
|
|
|
11
|
$event = 'end'; |
1692
|
4
|
|
|
|
|
12
|
trace "row $event $text\n" if TABLE_TRACE; |
1693
|
4
|
|
|
|
|
20
|
&$action; |
1694
|
|
|
|
|
|
|
|
1695
|
|
|
|
|
|
|
} |
1696
|
|
|
|
|
|
|
|
1697
|
0
|
|
|
|
|
0
|
$text = pop_output; |
1698
|
|
|
|
|
|
|
|
1699
|
0
|
50
|
|
|
|
0
|
if ( defined( my $action = $do_on_event{'table'} ) ) |
1700
|
|
|
|
|
|
|
{ # end of table |
1701
|
|
|
|
|
|
|
|
1702
|
0
|
|
|
|
|
0
|
$event = 'end'; |
1703
|
0
|
|
|
|
|
0
|
trace "table $event $text\n" if TABLE_TRACE; |
1704
|
0
|
|
|
|
|
0
|
&$action; |
1705
|
|
|
|
|
|
|
|
1706
|
|
|
|
|
|
|
} |
1707
|
|
|
|
|
|
|
|
1708
|
0
|
|
|
|
|
0
|
push_output(); |
1709
|
0
|
|
|
|
|
0
|
trace "end of table ($next_text)\n" if TABLE_TRACE; |
1710
|
0
|
|
|
|
|
0
|
output($next_text); |
1711
|
|
|
|
|
|
|
|
1712
|
|
|
|
|
|
|
} else { |
1713
|
|
|
|
|
|
|
|
1714
|
|
|
|
|
|
|
#push_output(); |
1715
|
|
|
|
|
|
|
|
1716
|
|
|
|
|
|
|
} |
1717
|
|
|
|
|
|
|
|
1718
|
|
|
|
|
|
|
# paragraph style |
1719
|
4
|
0
|
33
|
|
|
16
|
if ( defined($cstylename) and $cstylename ne '' ) |
1720
|
|
|
|
|
|
|
{ # end of previous style |
1721
|
|
|
|
|
|
|
|
1722
|
4
|
|
|
|
|
24
|
$style = $cstylename; |
1723
|
|
|
|
|
|
|
|
1724
|
|
|
|
|
|
|
} else { |
1725
|
|
|
|
|
|
|
|
1726
|
4
|
|
|
|
|
9
|
$cstylename = $style = 'par'; # no better solution |
1727
|
|
|
|
|
|
|
|
1728
|
|
|
|
|
|
|
} |
1729
|
|
|
|
|
|
|
|
1730
|
4
|
|
|
|
|
9
|
$par_props{'stylename'} = $cstylename; # the current style |
1731
|
|
|
|
|
|
|
|
1732
|
0
|
50
|
|
|
|
0
|
if ( $par_props{intbl} ) { # paragraph in tbl |
|
|
0
|
|
|
|
|
|
1733
|
|
|
|
|
|
|
|
1734
|
0
|
|
|
|
|
0
|
trace "process cell content: $text\n" if TABLE_TRACE; |
1735
|
|
|
|
|
|
|
|
1736
|
0
|
0
|
|
|
|
0
|
if ( defined( my $action = $do_on_event{$style} ) ) { |
|
|
50
|
|
|
|
|
|
1737
|
|
|
|
|
|
|
|
1738
|
0
|
|
|
|
|
0
|
( $style, $event, $text ) = ( $style, 'end', pop_output ); |
1739
|
0
|
|
|
|
|
0
|
&$action; |
1740
|
|
|
|
|
|
|
|
1741
|
|
|
|
|
|
|
} elsif ( defined( $action = $do_on_event{'par'} ) ) { |
1742
|
|
|
|
|
|
|
|
1743
|
|
|
|
|
|
|
#($style, $event, $text) = ('par', 'end', pop_output); |
1744
|
0
|
|
|
|
|
0
|
( $style, $event, $text ) = ( $style, 'end', pop_output ); |
1745
|
0
|
|
|
|
|
0
|
&$action; |
1746
|
|
|
|
|
|
|
|
1747
|
|
|
|
|
|
|
} else { |
1748
|
|
|
|
|
|
|
|
1749
|
4
|
|
|
|
|
9
|
warn; |
1750
|
|
|
|
|
|
|
|
1751
|
|
|
|
|
|
|
} |
1752
|
|
|
|
|
|
|
|
1753
|
4
|
|
|
|
|
6
|
push_output(); |
1754
|
|
|
|
|
|
|
|
1755
|
|
|
|
|
|
|
#} elsif (defined (my $action = $do_on_event{'par_styles'})) { |
1756
|
|
|
|
|
|
|
} elsif ( defined( my $action = $do_on_event{$style} ) ) { |
1757
|
|
|
|
|
|
|
|
1758
|
4
|
|
|
|
|
25
|
( $style, $event, $text ) = ( $style, 'end', pop_output ); |
1759
|
3
|
|
|
|
|
18
|
&$action; |
1760
|
18
|
|
|
|
|
38
|
flush_top_output(); |
1761
|
3
|
|
|
|
|
7
|
push_output(); |
1762
|
|
|
|
|
|
|
|
1763
|
|
|
|
|
|
|
} elsif ( defined( $action = $do_on_event{'par'} ) ) { |
1764
|
|
|
|
|
|
|
|
1765
|
|
|
|
|
|
|
#($style, $event, $text) = ('par', 'end', pop_output); |
1766
|
3
|
|
|
|
|
17
|
( $style, $event, $text ) = ( $style, 'end', pop_output ); |
1767
|
2
|
|
|
|
|
15
|
&$action; |
1768
|
|
|
|
|
|
|
flush_top_output(); |
1769
|
|
|
|
|
|
|
push_output(); |
1770
|
|
|
|
|
|
|
|
1771
|
|
|
|
|
|
|
} else { |
1772
|
|
|
|
|
|
|
|
1773
|
|
|
|
|
|
|
trace "no definition for '$style' in %do_on_event\n" if STYLE_TRACE; |
1774
|
|
|
|
|
|
|
flush_top_output(); |
1775
|
|
|
|
|
|
|
push_output(); |
1776
|
|
|
|
|
|
|
|
1777
|
|
|
|
|
|
|
} |
1778
|
|
|
|
|
|
|
# redefine this!!! |
1779
|
|
|
|
|
|
|
$cli = $par_props{'li'}; |
1780
|
|
|
|
|
|
|
$styledef = ''; |
1781
|
|
|
|
|
|
|
$par_props{'bullet'} = $par_props{'number'} = $par_props{'tab'} = 0; # |
1782
|
|
|
|
|
|
|
|
1783
|
|
|
|
|
|
|
}, |
1784
|
|
|
|
|
|
|
# Resets to default paragraph properties |
1785
|
|
|
|
|
|
|
# Stop inheritence of paragraph properties |
1786
|
|
|
|
|
|
|
|
1787
|
|
|
|
|
|
|
'pard' => sub { |
1788
|
|
|
|
|
|
|
|
1789
|
|
|
|
|
|
|
# !!!-> reset_par_props() |
1790
|
|
|
|
|
|
|
foreach (qw(qj qc ql qr intbl li)) { |
1791
|
|
|
|
|
|
|
|
1792
|
|
|
|
|
|
|
$par_props{$_} = 0; |
1793
|
|
|
|
|
|
|
|
1794
|
|
|
|
|
|
|
} |
1795
|
|
|
|
|
|
|
|
1796
|
|
|
|
|
|
|
foreach (qw(list_item)) { |
1797
|
|
|
|
|
|
|
|
1798
|
|
|
|
|
|
|
$par_props{$_} = ''; |
1799
|
|
|
|
|
|
|
|
1800
|
|
|
|
|
|
|
} |
1801
|
|
|
|
|
|
|
|
1802
|
|
|
|
|
|
|
}, |
1803
|
|
|
|
|
|
|
|
1804
|
|
|
|
|
|
|
# ########################### |
1805
|
|
|
|
|
|
|
|
1806
|
|
|
|
|
|
|
'pn' => sub { # Turn on PARAGRAPH NUMBERING |
1807
|
|
|
|
|
|
|
|
1808
|
|
|
|
|
|
|
#trace "($_[CONTROL], $_[ARG], $_[EVENT])" if TRACE; |
1809
|
|
|
|
|
|
|
|
1810
|
|
|
|
|
|
|
if ( $_[EVENT] eq 'start' ) { |
1811
|
|
|
|
|
|
|
|
1812
|
|
|
|
|
|
|
%pn = (); |
1813
|
|
|
|
|
|
|
$control[TOP]->{"$_[CONTROL]$_[ARG]"} = 1; |
1814
|
|
|
|
|
|
|
|
1815
|
|
|
|
|
|
|
} else { |
1816
|
|
|
|
|
|
|
|
1817
|
|
|
|
|
|
|
# I don't like this!!! redesign the parser??? |
1818
|
|
|
|
|
|
|
trace("Level: $pn{level} - Type: $pn{type} - Bullet: $pn{bullet}") |
1819
|
|
|
|
|
|
|
if LIST_TRACE; |
1820
|
|
|
|
|
|
|
$par_props{list_item} = \%pn; |
1821
|
|
|
|
|
|
|
|
1822
|
|
|
|
|
|
|
} |
1823
|
|
|
|
|
|
|
|
1824
|
|
|
|
|
|
|
}, |
1825
|
|
|
|
|
|
|
|
1826
|
|
|
|
|
|
|
'pnlvl' => sub { # Paragraph level $_[ARG] is a level from 1 to 9 |
1827
|
|
|
|
|
|
|
|
1828
|
|
|
|
|
|
|
$pn{level} = $_[ARG]; |
1829
|
|
|
|
|
|
|
|
1830
|
|
|
|
|
|
|
}, |
1831
|
|
|
|
|
|
|
|
1832
|
|
|
|
|
|
|
'pnlvlbody' => sub { # Paragraph level 10 |
1833
|
|
|
|
|
|
|
|
1834
|
|
|
|
|
|
|
$pn{level} = 10; |
1835
|
|
|
|
|
|
|
|
1836
|
|
|
|
|
|
|
}, |
1837
|
|
|
|
|
|
|
|
1838
|
|
|
|
|
|
|
'pnlvlblt' => sub { # Paragraph level 11, processs the 'pntxtb' group |
1839
|
|
|
|
|
|
|
|
1840
|
|
|
|
|
|
|
$pn{level} = 11; # bullet |
1841
|
|
|
|
|
|
|
|
1842
|
|
|
|
|
|
|
}, |
1843
|
|
|
|
|
|
|
|
1844
|
|
|
|
|
|
|
'pntxtb' => sub { |
1845
|
|
|
|
|
|
|
|
1846
|
|
|
|
|
|
|
if ( $_[EVENT] eq 'start' ) { |
1847
|
|
|
|
|
|
|
|
1848
|
|
|
|
|
|
|
push_output(); |
1849
|
|
|
|
|
|
|
$control[TOP]->{"$_[CONTROL]$_[ARG]"} = 1; |
1850
|
|
|
|
|
|
|
|
1851
|
|
|
|
|
|
|
} else { |
1852
|
|
|
|
|
|
|
|
1853
|
|
|
|
|
|
|
$pn{'bullet'} = pop_output(); |
1854
|
|
|
|
|
|
|
|
1855
|
|
|
|
|
|
|
} |
1856
|
|
|
|
|
|
|
|
1857
|
|
|
|
|
|
|
}, |
1858
|
|
|
|
|
|
|
|
1859
|
|
|
|
|
|
|
'pntxta' => sub { |
1860
|
|
|
|
|
|
|
|
1861
|
|
|
|
|
|
|
if ( $_[EVENT] eq 'start' ) { |
1862
|
|
|
|
|
|
|
|
1863
|
|
|
|
|
|
|
push_output(); |
1864
|
|
|
|
|
|
|
$control[TOP]->{"$_[CONTROL]$_[ARG]"} = 1; |
1865
|
|
|
|
|
|
|
|
1866
|
|
|
|
|
|
|
} else { |
1867
|
|
|
|
|
|
|
|
1868
|
|
|
|
|
|
|
pop_output(); |
1869
|
|
|
|
|
|
|
|
1870
|
|
|
|
|
|
|
} |
1871
|
|
|
|
|
|
|
|
1872
|
|
|
|
|
|
|
}, |
1873
|
|
|
|
|
|
|
# Numbering Types |
1874
|
|
|
|
|
|
|
'pncard' => sub { # Cardinal numbering: One, Two, Three |
1875
|
|
|
|
|
|
|
$pn{type} = $_[CONTROL]; |
1876
|
|
|
|
|
|
|
}, |
1877
|
|
|
|
|
|
|
|
1878
|
|
|
|
|
|
|
'pndec' => sub { # Decimal numbering: 1, 2, 3 |
1879
|
|
|
|
|
|
|
$pn{type} = $_[CONTROL]; |
1880
|
|
|
|
|
|
|
}, |
1881
|
|
|
|
|
|
|
|
1882
|
|
|
|
|
|
|
'pnucltr' => sub { # Uppercase alphabetic numbering |
1883
|
|
|
|
|
|
|
$pn{type} = $_[CONTROL]; |
1884
|
|
|
|
|
|
|
}, |
1885
|
|
|
|
|
|
|
|
1886
|
|
|
|
|
|
|
'pnlcltr' => sub { # Lowercase alphabetic numbering |
1887
|
|
|
|
|
|
|
$pn{type} = $_[CONTROL]; |
1888
|
|
|
|
|
|
|
}, |
1889
|
|
|
|
|
|
|
|
1890
|
|
|
|
|
|
|
'pnucrm' => sub { # Uppercase roman numbering |
1891
|
|
|
|
|
|
|
$pn{type} = $_[CONTROL]; |
1892
|
|
|
|
|
|
|
}, |
1893
|
|
|
|
|
|
|
|
1894
|
|
|
|
|
|
|
'pnlcrm' => sub { # Lowercase roman numbering |
1895
|
|
|
|
|
|
|
$pn{type} = $_[CONTROL]; |
1896
|
|
|
|
|
|
|
}, |
1897
|
|
|
|
|
|
|
|
1898
|
|
|
|
|
|
|
'pntext' => sub { # ignore text content |
1899
|
|
|
|
|
|
|
|
1900
|
|
|
|
|
|
|
if ( $_[EVENT] eq 'start' ) { |
1901
|
|
|
|
|
|
|
|
1902
|
|
|
|
|
|
|
push_output(); |
1903
|
|
|
|
|
|
|
$control[TOP]->{"$_[CONTROL]$_[ARG]"} = 1; |
1904
|
|
|
|
|
|
|
|
1905
|
|
|
|
|
|
|
} else { |
1906
|
|
|
|
|
|
|
|
1907
|
|
|
|
|
|
|
pop_output(); |
1908
|
|
|
|
|
|
|
|
1909
|
|
|
|
|
|
|
} |
1910
|
|
|
|
|
|
|
|
1911
|
|
|
|
|
|
|
}, |
1912
|
|
|
|
|
|
|
#'tab' => sub { $par_props{'tab'} = 1 }, # special char |
1913
|
|
|
|
|
|
|
|
1914
|
|
|
|
|
|
|
'li' => sub { # line indent - value |
1915
|
|
|
|
|
|
|
|
1916
|
8
|
|
|
8
|
|
55
|
use constant LI_TRACE => 0; |
|
8
|
|
|
|
|
28
|
|
|
8
|
|
|
|
|
1362
|
|
1917
|
|
|
|
|
|
|
my $indent = $_[ARG]; |
1918
|
|
|
|
|
|
|
$indent =~ s/^-//; |
1919
|
|
|
|
|
|
|
trace "line indent: $_[ARG] -> $indent" if LI_TRACE; |
1920
|
|
|
|
|
|
|
$par_props{'li'} = $indent; |
1921
|
|
|
|
|
|
|
|
1922
|
|
|
|
|
|
|
}, ); |
1923
|
|
|
|
|
|
|
########################################################################### |
1924
|
|
|
|
|
|
|
|
1925
|
8
|
|
|
8
|
|
49
|
use vars qw(%not_processed); |
|
8
|
|
|
|
|
21
|
|
|
8
|
|
|
|
|
3127
|
|
1926
|
|
|
|
|
|
|
|
1927
|
|
|
|
|
|
|
END { |
1928
|
8
|
50
|
|
8
|
|
6852
|
if (@control) { |
1929
|
0
|
|
|
|
|
0
|
trace "END{} - Control stack not empty [size: ", @control + 0, "]: "; |
1930
|
0
|
|
|
|
|
0
|
foreach my $hash (@control) { |
1931
|
0
|
|
|
|
|
0
|
while ( my ( $key, $value ) = each %$hash ) { |
1932
|
0
|
|
|
|
|
0
|
trace "$key => $value"; |
1933
|
|
|
|
|
|
|
} |
1934
|
|
|
|
|
|
|
} |
1935
|
|
|
|
|
|
|
} |
1936
|
8
|
50
|
|
|
|
8
|
if ($LOG_FILE) { |
1937
|
0
|
|
|
|
|
0
|
select STDERR; |
1938
|
0
|
0
|
|
|
|
0
|
unless ( open LOG, "> $LOG_FILE" ) { |
1939
|
0
|
|
|
|
|
0
|
print qq^$::BASENAME: unable to output data to "$LOG_FILE"$::EOM^; |
1940
|
0
|
|
|
|
|
0
|
return 0; |
1941
|
|
|
|
|
|
|
} |
1942
|
0
|
|
|
|
|
0
|
select LOG; |
1943
|
0
|
|
|
|
|
0
|
my ( $key, $value ) = ( '', '' ); |
1944
|
0
|
|
|
|
|
0
|
while ( my ( $key, $value ) = each %not_processed ) { |
1945
|
0
|
|
|
|
|
0
|
printf LOG "%-20s\t%3d\n", "$key", "$value"; |
1946
|
|
|
|
|
|
|
} |
1947
|
0
|
|
|
|
|
0
|
close LOG; |
1948
|
0
|
|
|
|
|
0
|
print STDERR qq^See Informations in the "$LOG_FILE" file\n^; |
1949
|
|
|
|
|
|
|
} |
1950
|
|
|
|
|
|
|
} |
1951
|
|
|
|
|
|
|
1; |
1952
|
|
|
|
|
|
|
__END__ |