#!/bin/perl
#
# Jerome C. Parks
# June 17, 1996
#
# fmt.pl [ -s ] [ -{width} ] [ {inputfile} ]
# This program is in place of the normal unix program, fmt.  It takes in a
# text file and formats it to 72 characters wide, and blocks the text.
# If given a number, it will format the text to that size.
# If given the -s argument, it will keep return characters.
#

@defaults = @ARGV;
@reversed = reverse(@defaults);
$file = @reversed[0];
$width = 72; # default setting if not specified by user

if ((@reversed[0] eq "") || (@reversed[0]=~/-(.*)/)) { 
  print "Usage: fmt.pl [ -s ] [ -{width} ] [ {inputfile} ]\n\n";
  exit;
}

foreach $L (@defaults) {
  if ($L eq "-s") {
	$new_lines = "Yes";
  } elsif ($L=~/\-(.*)/) {
	$width = $1;
  }
}

&format($file,$width,$new_lines);
exit;

############################ SUBROUTINES #####################################

# This subroutine takes in the file name to read from, the width, and whether
# this will be formatted as block or saving the return characters.
# It then calls the subroutine format_lines to do the actal formatting.
sub format {
  local($file,$width,$new_lines) = @_;

  open(IN,"$file") || warn "Can't open $file for read";
  if ($new_lines) {
	@f=<IN>;
  } else {
	@f=<IN>;
	grep (s/\n$/ /,@f);
        grep (s/^\s*$/\n/,@f);
  }
  close(IN);

  if ($new_lines) { # Case of maintaining the return characters
	foreach $L (@f) {
	  if (length($L) <= $width) {
		print $L;
	  } else {
		&format_lines($L,$width,$new_lines);
	  }
	}
  } else { # For block formatting
	while ($L .= shift(@f)) {
	  if ($L=~/\n$/) {
		&format_lines($L,$width,$new_lines);
		$L = "";
	  }
	}
  }

} # end subroutine format

# This subroutine takes in the Line and the width that the line will be 
# formatted to.  If the individual words are too long (that is, length of
# line is less than length of individual word), then the word will be
# split up over the two lines.
sub format_lines {
  local($Line,$width,$new_lines) = @_;
  local($previous_word,$previous_letter);
  $Line=~s/\t/BBBBBBB /g;

  @g = split(/ /,$Line);
  foreach $word (@g) {
	if ($word eq "BBBBBBB") {
	  $word=~s/BBBBBBB/      /;
	}
	if (length($word) <= $width) {
	  if ((length($previous_word)+length($word)) < $width) {
		if ($previous_word) {
		  $previous_word = "$previous_word $word";
		} else {
		  $previous_word = $word;
		}
                if ($previous_word=~/\n$/) {
		  if ($new_lines) {
			print "$previous_word";
		  } else {
                	print "$previous_word\n";
		  }
                  $previous_word = "";
                }
	  } else {
		print "$previous_word\n";
		$previous_word = $word;
	  }
	} else {
	  @h = split(//,$word);
	  foreach $letter (@h) {
		if ((length($letter)+length($previous_letter)) <= $width) {
		  $previous_letter .= $letter;
		} else {
		  print "$previous_letter\n";
		  $previous_letter = $letter;
		}
	  }
	  if ($new_lines) {
		print $previous_letter;
	  } else {
		$previous_word =  $previous_letter;
	  }
	}
  }

} # end subrtoutine format_lines;
