########################################################################
#  Copyright (c) 1999 Annelise Anderson
#  All rights reserved.
# 
#  Redistribution and use in source and binary forms, with or without
#  modification, are permitted provided that the following conditions
#  are met:
#  1. Redistributions of source code must retain the above copyright
#     notice, this list of conditions and the following disclaimer.
#  2. Redistributions in binary form must reproduce the above copyright
#     notice, this list of conditions and the following disclaimer in the
#     documentation and/or other materials provided with the distribution.
# 
#  THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
#  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
#  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
#  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
#  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
#  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
#  OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
#  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
#  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
#  OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
#  SUCH DAMAGE.
# 
# 	$Id: pcl.awk,v 1.0 1999/08/26 aanderson Exp $
#######################################################################
 
# pcl.awk processes files from a text editor for printing.  
# It adjusts line lengths using the size of the type, which it
# reads from pcl codes placed in the file, and font width.  It 
# adjusts vertical line spacing using type size. If pcl codes to
# set up the printer to accept unix line endings are used, no
# printing filters are necessary.  It accepts four command-line
# variables, TABLEN, port, land, and justify.  (It attempts to
# justify only fixed-width fonts, and does so imperfectly.)  The
# variables port and land set the default characters per line to
# print for courier 12 point (10 pitch) for portrait and landscape
# printing respectively; other fonts and font sizes use this info
# to determine characters per line to print. 

BEGIN { 
	TABLEN = "   "
	port = 66
	land = 92
	justify = 0
	blankline = "^[ \t]*$"
	orient = 0
	typesize = 12
	pitch = 10
	}

# If a block of text is marked as a table, print each record 
# without further processing, thus preserving white space; delete 
# markers.  Best to put markers on separate lines.  These
# lines will print as blanks.

/TBLB/,/TBLE/ {
	if ($0 ~ /TBLB/)
		sub(/TBLB/,"")
	else if ($0 ~ /TBLE/)
		sub(/TBLE/,"")
	else print ($0)
		next
}

function do_charperline() {
	if ( orient == 0 )
		charperline = int(port * (12 / typesize) * (50.7 / fontindex))
	else if ( orient == 1 )
		charperline = int(land * (12 / typesize) * (50.7 / fontindex))
	return
}

function do_charperline2() {
	if ( orient == 0 ) 
		charperline = int(port * 12 / typesize) 
	if ( orient == 1 )
		charperline = int(land * 12 / typesize) 
	return
}

function do_charperline3() {
	if ( orient == 0 ) 
		charperline = int(port * 12 / ( 120 / pitch )) 
	if ( orient == 1 )
		charperline = int(land * 12 / ( 120 / pitch )) 
	return
}

# if document has no font codes to determine charperline, set up default;
# needs to be done after port and land variables become available if
# they are changed on the command line

{
if ( charperline == "" ) 
	do_charperline2()
}

# print blank lines as they occur

$0 ~ blankline {
	print 
}

# preserve initial spaces and tabs; substitute spaces for tabs (change
# TABLEN above to adjust).  Split lines into an array of words; put two 
# spaces after words ending with most punctuation marks, otherwise one.

$0 !~  blankline  {
	indentstr = ""
	if ( match($0,/^[ \t]+/ ))
	{ 
		indentstr = substr($0,RSTART,RLENGTH  )
		gsub(/\t/,TABLEN,indentstr )
	} 
	nf = split( $0, word, "[ \t]+" )
	{ 
		for ( i = 1; i <= nf; i++ )
		{
			if (word[i] ~ /[.?!:;]$/ )
				line = sprintf( "%s%s", word[i] , "  " )
			else 
				line = sprintf( "%s%s", word[i], " " )  
			oldline = newline 
			if (( i == 1 )  && (indentstr != "" ))
				newline = indentstr line 
			else newline = newline line
# get and save orientation (landscape or portrait)
			orientstr = $0
			while (match(orientstr,/&l[01]O/))
			{
				orient = substr(orientstr,RSTART + 2, 1)
				orientstr = substr(orientstr,RSTART + RLENGTH)
			}
# get the printer font codes and save the font size; calculate the
# length of the printer font and other codes so it can be deducted
# from permissible line length
	
			codelen = 0 
			# do all short code lengths
			strline = newline
			while ( match(strline,/[&(][a-z][-+]?[0-9]*[A-Z@]/ ))
			{
				codelen += RLENGTH  + 1  
				strline = substr(strline,RSTART + RLENGTH)
			}
			# do code lengths for fonts v or h except lineprinter
			if ( match(newline,/s[01]p[0-9][0-9]?[vh][0-5]s[0-4]b[0-9]+T/ ))
				codelen += RLENGTH + 2
			
			# do code lengths for dj fonts with both v and h 
			if ( match(newline,/s0p[0-9][0-9]?\.?[0-9]?[0-9]?h[0-9][0-9]?\.?[0-9]?[0-9]?v[0-5]s[0-3]b[0-9]+T/ )) 
			{
				codelen += RLENGTH + 2
				prop = 0
				afontstr = substr(newline, RSTART, RLENGTH )
				parts = split(afontstr,strparts, "[hv]" )
				pitch = substr(strparts[1], 4, (length(strparts[1]) -3))
				typesize = strparts[2]
				do_charperline3()
			}

			# all lj fixed fonts except lineprinter (no v)
			if ( match(newline,/s0p[0-9][0-9]?h[0-5]s[0-3]b[0-9]+T/ ))
			{
				prop = 0
				pitch = substr(newline, RSTART + 3, 2) # problem?
				typesize = 120 / pitch
				do_charperline2()
			}
			# special handling for lineprinter (lj)
			# probably unnecessary given dj block 
			if (match(newline,/s0p16.67h8.5v0s0b0T/))
			{
				codelen += RLENGTH + 2
				prop = 0
				pitch = 16.67
				typesize = 120 / 16.67  
				do_charperline2()
			}
			# all proportional-width fonts
			if ( match(newline,/s1p[0-9][0-9]?v[0-5]s[0-4]b[0-9]+T/ ))
			{
				prop = 1
				typesize = substr(newline, RSTART + 3, 2)  # ok
				fontstr = substr(newline, RSTART , RLENGTH)
				fontindex = 0               # may be unnec
				# start of font block: all univers not condensed
				if (fontstr ~ /v[01]s[03]b4148T|v[01]s[03]b52T/)  
				{
					fontindex = 41.9
					do_charperline()
				}
				# end of font block 
				# start of font block: universcond, universcondi 
				else if (fontstr ~ /v[45]s0b4148T/)  
				{
					fontindex = 29.4
					do_charperline()
				}
				# end of font block 
				# start of font block: universboldcond, universboldcondi 
				else if (fontstr ~ /v[45]s3b4148T/)  
				{
					fontindex = 34.5
					do_charperline()
				}
				# end of font block 
				# cgtimes and times new roman, reg and ital; clarendon condensed
				# start of font block
				else if (fontstr ~ /v[01]s0b4101T|v[01]s0b16901T|v4s3b4140T/)  
				{
					fontindex = 36.2
					do_charperline()
				}                                      
				# end of font block
				# omega, omega ital, garamond halbfett
				# start of font block
				else if (fontstr ~ /v[01]s0b4113T|v0s3b4197T/)  
				{
					fontindex = 38.8
					do_charperline()
				}                                       
				# end of font block 
				# start of font block: omegab, omegabi, arial, ariali 
				else if (fontstr ~ /v[01]s3b4113T|v[01]s0b16602T|v0s3b16602T/)  
				{
					fontindex = 40
					do_charperline()
				}                                       
				# end of font block 
				# start of font block: coronet, marigold
				else if (fontstr ~ /v1s0b4116T|v0s0b4297T/)  
				{
					fontindex = 22
					do_charperline()
				} 
				# end of font block
				# start of font block: cgtb, tnb, gkh, albmed
				else if (fontstr ~ /v0s3b4101T|v0s3b16901T|v1s3b4197T|v0s1b4362T/)  
				{
					fontindex = 38.3
					do_charperline()
				} 
				# end of font block
				# start of font block: antique olive, antique olive ital
				# if (match(fontstr,/v[01]s0b4168T/))  
				else if (fontstr ~ /v[01]s0b4168T/)  
				{
					fontindex = 47
					do_charperline()
				} 
				# end of font block
				# start of font block: arialbi, albextrab, symbol
				else if (fontstr ~ /v1s3b16602T|v0s4b4362T|v0s0b16686T/)  
				{
					fontindex = 43
					do_charperline()
				} 
				# end of font block
				# start of font block: antique olive bold
				else if (fontstr ~ /v0s3b4168T/)  
				{
					fontindex = 52.2
					do_charperline()
				} 
				# end of font block
				# if there's no font block, default
				else
				{
					if (orient == 0 )
						charperline = int(( port * 12 ) / ( 0.7 * typesize ))
					if (orient == 1 )
						charperline = int(( land * 12 ) / ( 0.7 * typesize ))
				}
			}

# if a series of words is too long to print, drop off a word and print
# that line.  Get another word and test again.  If the array has no more 
# words, print what's left.  Insert code for line spacing.
			
			if ((( length( newline)) - codelen ) > charperline )
			{ 
				printline = oldline
				newline = line
				if ( justify  && !prop )
				{
					# get ltrcount before more code is added, establish hmi
					ltrcount = length(printline) 
					if ( ltrcount && charperline )
					{
						hmi = 120 / (( ltrcount / (charperline + codelen)) * pitch )
						hmicode = sprintf("&k%sH",hmi)
					}
				}
				fontmatch = 0
				# next line covers vh (deskjets) too
				if ( match(printline,/s[01]p[0-9][0-9]?[vh][0-5]s[0-4]b[0-9]+T/ ))
				{	
					fontmatch = 1 				# maybe add this
					# print the vertical motion index code for single space
					printf("&l%sC" , (int((typesize +1) * 2/3)) )
					typestr = substr(printline, RSTART,  RLENGTH) 
					# hmi code needs to go after typestr, before 
					# the rest of the printline
					if ( justify && !prop )
					{
						sub(typestr, typestr hmicode, printline) 
					}
				}
				if ( !fontmatch )       
				{	
					if ( justify && !prop )  # error here now (seems okay)
						printf("%s", hmicode)
				}
				if (printline ~ /s0p16.67h8.5v0s0b0T/)
				{
					printf("&l%sC" , (int((typesize +1) * 2/3)) )
				}
				printf ( "%s\n",  printline )
			}
			if ( i < nf )
				continue
			else if  ( i == nf )  
			{
			# vh added here 
				
				if (newline ~ /s[01]p[0-9][0-9]?[vh][0-5]s[0-4]b[0-9]+T|s0p[0-9][0-9]?\.?[0-9]?[0-9]?h[0-9][0-9]?\.?[0-9]?[0-9]?v[0-5 ]s[0-3]b[0-9]+T/ )
				printf("&l%sC", (int((typesize +1) * 2/3)) )
				printf ( "%s\n", newline )
				newline = "" 
			}
		}
	}
}
