Text::WrapProp - proportional line wrapping to form simple paragraphs


Text-WrapProp documentation Contained in the Text-WrapProp distribution.

Index


Code Index:

NAME

Top

Text::WrapProp - proportional line wrapping to form simple paragraphs

SYNOPSIS

Top

	use Text::WrapProp

	print wrap_prop($text, $width, $ref_width_table);

	use Text::WrapProp qw(wrap_prop);

DESCRIPTION

Top

Text::WrapProp::wrap_prop() is a very simple paragraph formatter for proportional text. It formats a single paragraph at a time by breaking lines at word boundries. You must supply the column width in floating point units which should be set to the full width of your output device. A reference to a character width table must also be supplied. The width units can be any metric you choose, as long as the column width and the width table use the same metric.

Proportional wrapping is most commonly used in the publishing industry. In the HTML age, custom proportional wrapping is less often performed as the browser performs the calculations automatically.

EXAMPLE

Top

	my @width_table = (0.05) x 256;
	print wrap_prop("This is a bit of text that forms a normal book-style paragraph. Supercajafrajalisticexpialadocious!", 4.00, \@width_table);

BUGS

Top

It's not clear what the correct behavior should be when WrapProp() is presented with a word that is longer than a line. The previous behavior was to die. Now the word is split at line-length.

AUTHOR

Top

James Briggs <71022.3700@compuserve.com>, styled after Text::Wrap.


Text-WrapProp documentation Contained in the Text-WrapProp distribution.

package Text::WrapProp;

use strict;
use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);

require Exporter;

@ISA = qw(Exporter AutoLoader);
# Items to export into callers namespace by default. Note: do not export
# names by default without a very good reason. Use EXPORT_OK instead.
# Do not simply export all your public functions/methods/constants.
@EXPORT = qw( wrap_prop
	
);

$VERSION = '0.01';

# Preloaded methods go here.

# Autoload methods go after =cut, and are processed by the autosplit program.

1;

sub wrap_prop {
   my ($text, $width, $ref_width_table) = @_;

   my @width_table = @$ref_width_table;

   return '' if $text eq '';

   # simplify whitespace, including newlines
   $text =~ s/\s+/ /gs;

   my $cursor = 0; # width so far of line
   my $c;          # current character
   my $out;        # output buffer
   my $nextline = '';

   my $i=0;

   my $ltext = length $text;

# tried regex scanning, but 50% slower than C-style char processing!
#  like this... while ($text =~ /(.)/gcs) {
         
   while ($i < $ltext) {
         # pop off next character
         $c    = substr($text,$i++,1);
         
         # don't need leading spaces at start of line
         next if $nextline eq '' and $c eq ' ';

         # see if character will fit on line - but don't include if too long
         if ($cursor + $width_table[ord $c] <= $width) {
            # another character fits
            $nextline .= $c;
            $cursor += $width_table[ord $c];
         }
         else {
            # find where we can wrap by checking backwards for separator
            my $j = length($nextline);
            foreach (split '', reverse $nextline) { # find separator
               $j--;
               last if /( |:|;|,|\.|-|\(|\)|\/)/o; # separator characters
            }

            # see if no separator found
            if (!$j) { # no separator, so just truncate line right here
               $i--; # rerun on $c
               $out .= $nextline."\n";
            }
            # 
            else { # separator found, so break line at separator
               $i -= length($nextline) - $j; # rerun characters after separator
               $out .= substr($nextline, 0, $j+1)."\n";
            }

            $nextline = '';
            $cursor = 0;
         }
   }

   $out.$nextline;
}

__END__