1package PerlPoint::Converters;
2
3$VERSION = "1.0205";
4
5use File::Copy;
6use Cwd;
7use Carp;
8use Exporter;
9@ISA = qw(Exporter);
10
11@EXPORT_OK = qw(
12  replace_keywords
13  update_file
14  copy_file
15  return_abs_path
16  relative_path
17  is_abs_path
18);
19use strict;
20
21=head1 NAME
22
23PerlPoint::Converters - README and common functions for PerlPoint converters
24
25=head1 README
26
27Covered topics:
28
29=over 4
30
31=item *
32
33Introduction
34
35=item *
36
37About PerlPoint-Converters
38
39=item *
40
41Prerequisits
42
43=item *
44
45What's new
46
47=item *
48
49Installation
50
51=item *
52
53Documentation
54
55=item *
56
57Test Cases
58
59=item *
60
61Bug Reports and Support
62
63=item *
64
65Credits
66
67=item *
68
69Licence
70
71=back
72
73=head2 Introduction
74
75PerlPoint is a simple text format which allows easy typing of text
76with headlines, bullet lists, normal text paragraphs, indented
77paragraphs for code examples etc., from which slides for presentations
78can be generated by a script without the need of proprietary software.
79Since there is a large variety of platforms which provide web browsers,
80HTML is a good choice for the output format. In principle, however, it
81is possible to generate each output format whose specification is
82known. At the moment there exist converters for HTML, LaTeX (alpha software)
83and SDF. The latter both may be used to generate printable output or to
84provide the basis for further processing.
85
86
87=head2 About PerlPoint-Converters
88
89This package provides two programs:
90
91  pp2html
92  pp2latex (still alpha software)
93
94They convert an ASCII file written in the `PerlPoint' language to a set
95of HTML files or to Latex Files respectively. The `PerlPoint' language
96was initially invented by Tom Christiansen as a simple means for
97preparing slides. The idea was to just write down your headings and
98bullet items and then use a simple perl script to create the slides:
99
100  =Header of first slide
101
102  * Use your favourite editor
103
104  * Start headings with a `='
105
106  * Bullets items start with an asterisk `*'
107
108The syntax of the original version was similar to POD and the layout
109of the slides was hard coded in Tom's pp2html script. The new syntax
110provides more felxibility and can be parsed with the PerlPoint::Parser
111from Jochen Stenzel's PerlPoint-Package.
112
113The following list persents some of the features of pp2html and pp2latex:
114
115  - HTML template files for header, footer and navigation bar
116  - Support of Frame Sets
117  - Support of the TreeControl Applet in tabel of contents
118  - Headers with different levels with or wihout numbering
119    (1, 1.1, 1.2, 2, ...)
120  - Hyperlinks to internal and external pages
121  - Automatic generation of table of contents and navigation links
122  - Automatic generation of index
123  - Bullet-Lists with standard <LI> bullets or with bullets from
124    a gif/jpeg file
125  - Numbered lists and definition lists
126  - Simple tables
127  - Simple text formatting possible
128
129For more information about the PerlPoint syntax and history please
130refer to the documentation in the PerlPoint-Package from Jochen Stenzel
131(perldoc PerlPoint::Parser) and to the provided documentation in the
132./doc/PPDOC subdirectory (after a successful "make" in ./doc :-)
133
134
135=head2 Prerequisits
136
137This version needs Perl5.005.
138
139The pp2html program uses the following packages which are available on CPAN
140or come with your Perl distribution:
141
142  Pod::Text
143  Getopt::Long
144  Getopt::ArgvFile
145  PerlPoint::Parser
146  PerlPoint::Backend
147  PerlPoint::Constants
148  PerlPoint::Tags::Basic;
149  PerlPoint::Tags::HTML;  (part of PerlPoint-Converters)
150  PerlPoint::Tags::LaTeX; (part of PerlPoint-Converters)
151
152The TreeApplet classes are contained in the pp2html_stypes subdirectory of this
153distribution. For more information about the TreeApplet classes refer to
154http://www.naturallyj.com.
155This distribution contains an older version which was freely available.
156
157
158=head2 What's new in this version
159
160This is version 1.00.
161You will need PerlPoint-Packet version 0.36 for this release.
162
163Please refer to file "Changes".
164
165=over 4
166
167=item NOTE:
168
169Documentation is not yet perfect, but hopefully better than before.
170Please try a "make" in ./doc and look at the documents which
171should have been created in ./doc/PPDOC
172
173=back
174
175=head2 Installation
176
177Just get the PerlPoint-Converters-<release>.tar.gz file and unpack it in a temp directory:
178
179  % tar zxvf PerlPoint-Converters-<release>.tar.gz
180  % cd PerlPoint-Converters-<release>
181  % perl Makefile.PL
182  % make
183  % make test
184  % make install
185
186  % cd ./doc
187  % make
188
189The main program is `pp2html'. Try `pp2html --help | less' to get more
190information.
191
192=head2 Documentation
193
194C<pp2hml> and C<pp2latex> have a --help option which displays
195Usage information and some documentation about the PerlPoint
196Language. For a more detailed description please refer to the
197POD documentation of the following Modules:
198
199 PerlPoint::Parser
200 PerlPoint::Anchors
201 PerlPoint::Backend
202 PerlPoint::Constants
203 PerlPoint::Tags
204 PerlPoint::Tags::Basic
205 PerlPoint::Tags::CPPP
206 PerlPoint::Tags::HTML
207 PerlPoint::Tags::LaTeX
208 PerlPoint::Tags::SDF
209
210Have also a look into the ./doc directory of your PerlPoint::Converters
211installation directory. There is a Makefile which produces the
212following PerlPoint documents:
213
214=over 4
215
216=item *
217
218Getting_Started
219
220=item *
221
222FAQ-pp2html
223
224=item *
225
226FAQ-parser
227
228=item *
229
230Writing-Converters
231
232=back
233
234
235=head2 Test Cases
236
237The examples test cases from the previous releases (ex_std_norm,
238ex_std_tree, ex_frm_norm and ex_frm_tree) have now been replaced
239with the documentation in the ./doc subdirectory.
240
241
242=head2 Bug Reports and Support
243
244Please send bug reports and requests to <lorenz.domke@gmx.de>
245There is also a mailing list for PerlPoint:
246
247  perlpoint@perl.org
248
249To join the mailing list, send a message to C<perlpoint-subscribe@perl.org>
250
251
252
253
254=head2 Credits
255
256Thanks to Tom Christiansen for the idea and first implementation
257of PerlPoint! And special thanks for his permission to use this
258name for our new implementation.
259
260Thanks to Jochen Stenzel who tested the first versions of pp2html
261and supplied the powerful PerlPoint-Package which is the base of
262this new implementation of pp2html.
263
264Thanks to Stephen Riehm who shared his ideas of extensions for
265the original software with us. The final language was basically
266designed by a team of Jochen, him and me.
267
268Thanks to Alex Sigel and Norbert Gruener who became our first
269testers outside the team and helped us by their usage reports.
270Special thanks to Alex for propagating the toolkit and his help
271to publish the software!
272
273
274=head2 Licence
275
276This module is free software, you can redistribute it and/or modify it
277under the terms of the Artistic License distributed with Perl version
2785.003 or (at your option) any later version. Please refer to the
279Artistic License that came with your Perl distribution for more
280details.
281
282The Artistic License should have been included in your distribution of
283Perl. It resides in the file named "Artistic" at the top-level of the
284Perl source tree (where Perl was downloaded/unpacked - ask your
285system administrator if you dont know where this is).  Alternatively,
286the current version of the Artistic License distributed with Perl can
287be viewed on-line on the World-Wide Web (WWW) from the following URL:
288http://www.perl.com/perl/misc/Artistic.html
289
290DISCLAIMER
291
292This software is distributed in the hope that it will be useful, but
293is provided "AS IS" WITHOUT WARRANTY OF ANY KIND, either expressed or
294implied, INCLUDING, without limitation, the implied warranties of
295MERCHANTABILITY and FITNESS FOR A PARTICULAR PURPOSE.
296
297The ENTIRE RISK as to the quality and performance of the software
298IS WITH YOU (the holder of the software).  Should the software prove
299defective, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR
300CORRECTION.
301
302IN NO EVENT WILL ANY COPYRIGHT HOLDER OR ANY OTHER PARTY WHO MAY CREATE,
303MODIFY, OR DISTRIBUTE THE SOFTWARE BE LIABLE OR RESPONSIBLE TO YOU OR TO
304ANY OTHER ENTITY FOR ANY KIND OF DAMAGES (no matter how awful - not even
305if they arise from known or unknown flaws in the software).
306
307Please refer to the Artistic License that came with your Perl
308distribution for more details.
309
310
311=head1 SYNOPSIS
312
313 use PerlPoint::Converters qw(
314                               replace_keywords
315                               update_file
316                               copy_file
317                             );
318
319 copy_file($from, $to);
320
321 update_file($from, $to);
322
323 $line = replace_keywords($line, $KEY_HASH_REF);
324
325=head1 DESCRIPTION
326
327This module contains some common functions which are
328useful for most PerlPoint converters.
329
330=head1 SUBROUTINES
331
332=cut
333
334sub replace_keywords { #{{{-----------------------------------------
335
336=head2 replace_keywords($line, $KEY_HASH_REF);
337
338Replace all occurences of certain keywords in $line with the
339values specified in the referenced hash.
340The keys in the hash must be lower case keywords.
341
342Example:
343
344 %OPT = (
345    title        => "PerlPoint Examples",
346    bot_left_txt => "Copyright A. User",
347 );
348
349 open(TPL, "a_template_file");
350 while(<TPL>){
351   print replace_keywords($_, \%OPT);
352 }
353
354This will replace "TITLE" with "PerlPoint Examples" and "BOT_LEFT_TXT"
355with "Copyright A. User".
356
357The supported keywords are:
358
359  TXT_CONTENTS
360  TXT_INDEX
361  PAGE_CNT
362  TITLE
363  BASE_LEFT_TXT
364  BASE_RIGHT_TXT
365  BASE_MIDDLE_TXT
366  BOT_LEFT_TXT
367  BOT_RIGHT_TXT
368  BOT_MIDDLE_TXT
369  TOP_LEFT_TXT
370  TOP_RIGHT_TXT
371  TOP_MIDDLE_TXT
372
373  BGCOLOR
374  FGCOLOR
375  BOT_BGCOLOR
376  TOP_BGCOLOR
377  IDX_BGCOLOR
378  TOC_BGCOLOR
379  BOT_FGCOLOR
380  TOP_FGCOLOR
381  IDX_FGCOLOR
382  TOC_FGCOLOR
383  LINKCOLOR
384  TOP_LINKCOLOR
385  BOT_LINKCOLOR
386  TOC_LINKCOLOR
387  IDX_LINKCOLOR
388  ALINKCOLOR
389  TOP_ALINKCOLOR
390  BOT_ALINKCOLOR
391  TOC_ALINKCOLOR
392  IDX_ALINKCOLOR
393  VLINKCOLOR
394  TOP_VLINKCOLOR
395  BOT_VLINKCOLOR
396  TOC_VLINKCOLOR
397  IDX_VLINKCOLOR
398
399  LABEL_NEXT
400  LABEL_PREV
401  LABEL_INDEX
402  LABEL_CONTENTS
403
404  SLIDE_PREFIX
405  SLIDE_SUFFIX
406
407  LOGO_IMAGE_FILENAME
408  IMAGE_REF
409  META_TAGS
410
411=cut
412
413  my ($line, $OPT) = @_;
414  my @KW = qw(
415  TXT_CONTENTS
416  TXT_INDEX
417  PAGE_CNT
418  TITLE
419  BASE_LEFT_TXT
420  BASE_RIGHT_TXT
421  BASE_MIDDLE_TXT
422  BOT_LEFT_TXT
423  BOT_RIGHT_TXT
424  BOT_MIDDLE_TXT
425  TOP_LEFT_TXT
426  TOP_RIGHT_TXT
427  TOP_MIDDLE_TXT
428
429  BGCOLOR
430  FGCOLOR
431  BOT_BGCOLOR
432  TOP_BGCOLOR
433  IDX_BGCOLOR
434  TOC_BGCOLOR
435  BOT_FGCOLOR
436  TOP_FGCOLOR
437  IDX_FGCOLOR
438  TOC_FGCOLOR
439  LINKCOLOR
440  TOP_LINKCOLOR
441  BOT_LINKCOLOR
442  TOC_LINKCOLOR
443  IDX_LINKCOLOR
444  ALINKCOLOR
445  TOP_ALINKCOLOR
446  BOT_ALINKCOLOR
447  TOC_ALINKCOLOR
448  IDX_ALINKCOLOR
449  VLINKCOLOR
450  TOP_VLINKCOLOR
451  BOT_VLINKCOLOR
452  TOC_VLINKCOLOR
453  IDX_VLINKCOLOR
454
455  LABEL_NEXT
456  LABEL_PREV
457  LABEL_INDEX
458  LABEL_CONTENTS
459
460  SLIDE_PREFIX
461  SLIDE_SUFFIX
462
463  LOGO_IMAGE_FILENAME
464  IMAGE_REF
465  META_TAGS
466
467  );
468  $line =~ s/SLIDE_PREFIX/$$OPT{slide_prefix}/g;
469     # special word boundary for SLIDE_PREFIX ...
470  foreach my $kw (@KW){
471    $line =~ s/\b$kw\b/$$OPT{lc($kw)}/g if defined $$OPT{lc($kw)};
472  }
473  return $line;
474
475} # replace_keywords  }}}
476
477sub copy_file { #{{{ -----------------------------------------------
478
479=head2 copy_file($from, $to, $verbose, $KEY_HASH_REF);
480
481Copy file C<$from> to file C<$to>. For binary files (! -T) the File::Copy
482method will be used. Text files are copied by reading from
483C<$from> and printing to C<$to>. All lines are
484treated with the C<replace_keywords> method.
485
486Prints a message to STDERR if $verbose is set to 1.
487
488=cut
489
490  # should work on each system ...
491  my ($from, $to, $verbose, $OPT) = @_;
492  print STDERR "... copying $from to $to\n" if $verbose;
493  if (! -T $from){
494    copy($from, $to); # (use correct mode for binary files)
495  } else { # should be text file ...
496    open(FROM, "< $from") or die "Can't open $from: $!\n";
497    open(TO  , "> $to")   or die "Can't open $to: $!\n";
498    while(<FROM>) {
499      print TO replace_keywords($_, $OPT);
500    }
501    close(FROM); close(TO);
502  }
503} # copy_file }}}
504
505sub update_file { #{{{ ---------------------------------------------
506
507=head2 update_file($from, $to, $verbose, $KEY_HASH_REF, $moveFlag);
508
509Update file C<$from> to file C<$to> if necessary. For binary files (! -T)
510the File::Copy method will be used. Files are only copied if the
511modification date of C<$to> is older than the modification date of C<$from>.
512
513Text files are B<always> copied by reading from
514C<$from> and printing to C<$to> because keywords might have
515changed. All lines are treated with the C<replace_keywords> method.
516
517Prints a message to STDERR if $verbose is set to 1.
518
519The source file is removed if the $moveFlag was set to a true value,
520which means that the function performs a move instead of a copy.
521
522=cut
523
524  my ($from, $to, $verbose, $OPT, $move) = @_;
525  # check, if update is really needed:
526  return if $to eq $from;
527  if (! -e $from) {
528    croak "\n**** file not  found: $from\n"; ## should not occur!
529  }
530  # copy:
531  if (! -T $from){ # binary file ?
532    if (-e $to){
533      my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$time2) = stat(_);
534      my $time1;
535      ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$time1) = stat($from);
536      return if $time1 <= $time2;
537    }
538    print STDERR "... copying $from to $to\n" if $verbose;
539    copy($from, $to); # (use correct mode for binary files)
540  } else { # should be text file ...
541    ## always copy, because the keywords might have changed !
542    print STDERR "... copying $from to $to\n" if $verbose;
543    open(FROM, "< $from") or die "Can't open $from: $!\n";
544    open(TO  , "> $to")   or die "Can't open $to: $!\n";
545    while(<FROM>) {
546      print TO replace_keywords($_, $OPT);
547    }
548    close(FROM); close(TO);
549  }
550
551  # delete file, if necessary
552  unlink($from) if defined($move) and $move;
553} # update_file }}}
554
555sub return_abs_path { #{{{ -----------------------------------------
556
557=head2 $abs_path = return_abs_path($pathname)
558
559Given a relative or absolute pathname: return absolute pathname
560$pathname must exist and either be absolute or relative to
561current working directory.
562
563=cut
564
565  my $path = shift;
566  my $cwd = cwd;
567  chdir $path or croak "Cannot cd to $path\n";
568  my $abspath = cwd;
569  chdir $cwd or croak "Cannot cd back to $cwd\n";
570  return $abspath;
571} # return_abs_path }}}
572
573sub is_abs_path { #{{{-----------------------------------------------
574
575=head2 is_abs_path($pathname)
576
577Return 1 if $pathname is an absolute pathname, i. e. it starts with
578a slash "/" or with a character, followed by a colon and and a slash
579or backslash: "C:/bla bla" or "T:\foo\bar". Otherwise return 0.
580
581=cut
582
583  my $path = shift;
584  return 1 if
585    $path =~ m#^\s*/# or
586    $path =~ m#^\s*[a-z]:[/\\]#i;
587  return 0;
588} # is_abs_path }}}
589
590sub relative_path { #{{{--------------------------------------------
591
592=head2 $rel_path = relative_path($path1, $path2)
593
594Return relative path from $path1 to $path2.
595
596    path           C:/this/is/my/test/foo
597    path2          C:/this/is/my/test/images/new
598    ==> rel_path   ../images/new
599
600=cut
601
602  my ($path1, $path2) = @_;
603  my $rel = "";
604  my ($p1, $p2) = ("$path1/", "$path2/");
605
606  if (! is_abs_path($path1)){
607    if (-d $path1) {
608      $p1 = return_abs_path($path1) . "/";
609    } else {
610        # try to construct abs path:
611       $p1 = cwd() . "/$path1/";
612    }
613  }
614  if (! is_abs_path($path2)){
615    if (-d $path2) {
616      $p2 = return_abs_path($path2) . "/";
617    } else {
618        # try to construct abs path:
619       $p2 = cwd() . "/$path2/";
620    }
621  }
622
623#print "p1: $p1\n";
624#print "p2: $p2\n";
625  # reduce multiple / and \ to single /
626  $p1 =~ s#[\\]+#/#g;
627  $p1 =~ s#/+#/#g;
628  $p2 =~ s#[\\]+#/#g;
629  $p2 =~ s#/+#/#g;
630#print "1  p1: $p1\n";
631#print "1  p2: $p2\n";
632  return "." if uc($p1) eq uc($p2);
633
634
635# First: cut common part of pathname
636  while($p1 and $p2){
637    my $h1 = "";
638    my $h2 = "";
639    if ($p1 =~ m#([^/]+)/#){
640       $h1 = $1;
641    }
642    if ($p2 =~ m#([^/]+)/#){
643       $h2 = $1;
644    }
645#print "11  h1: $h1\n";
646#print "11  h2: $h2\n";
647    if (uc($h1) eq uc($h2)){
648      # is ok for windows and should work under UNIX as long as
649      # there are not two different dir names which are only distinct in
650      # letter case
651      substr($p1, 0, length($h1)+1) = "";  # cut leading part/
652      substr($p2, 0, length($h2)+1) = "";  # cut leading part/
653    } else {
654      last;
655    }
656#print "11  p1: $p1\n";
657#print "11  p2: $p2\n";
658  }
659#print "2  p1: $p1\n";
660#print "2  p2: $p2\n";
661# Second: construct relative pathname from $p1 to $p2:
662#    go up from $p1 to common root:
663   $p1 =~ s#^/##;
664   $p2 =~ s#^/##;
665   while(index($p1, "/")>=0){
666#print "33  p1: $p1\n";
667     $rel .= "../";
668     substr($p1, 0, index($p1,"/")+1) = "";
669   }
670#    append path to $p2
671  $rel .= $p2;
672  $rel =~ s#/$##;
673#print "---rel: $rel\n";
674  return $rel;
675} # relative_path }}}
676
677=head1 AUTHOR
678
679Lorenz Domke <lorenz.domke@gmx.de>
680
681
682=cut
683
6841
685
686__END__
687
688# vim:foldmethod=marker:foldcolumn=4
689
690