#!/usr/bin/env python
# +---------------------------------------------------------------------------+
# | Standard document print formatting software 			      |
# | Version:  1.0    08 March 2009                                            |
# | (C) Copyright David Goodwin, 2009                                         |
# +---------------------------------------------------------------------------+

# Standard document print formatting script
# Performs some simple printer formatting on a plain-text document
# goodwin 08mar09 [initial version]


# Usage Information:
#  ./print-format file.txt | nc printer.example.com 9100
 
# Two tags are supported in the input document:
#   !@#/title=		Sets the document title
#			Example:  !@#/title=The Document Title
#   !@#/page-break	Inserts a page-break here
#			Example:  !@#/page-break

# This program inserts a header containing the page number and document title, 
# as well as a footer containing the page number and optionally the filename.

# Note that the input document should be formatted in a way that prevents the
# printer from wrapping lines - any wrapped lines will likely cause page breaks
# to occur at the wrong places.

# If no document title is set, the filename is used as the document title. This
# can be changed by setting current_page_title below to a different string
# value.

# Page dimensions are controlled using the variables defined below.
page_width = 79			# Page width (in characters)
lines_per_page = 63		# Page length (in lines)
filename_in_footer = True      # If True, the filename will appear in the footer
filename = ""			# Default file to load and format
current_page_title = filename	# Default page title

# If [filename] is set above, that file will be loaded when none is specified
# on the command line. [current_page_title] is the default page title when none
# is specified in the document. If [filename_in_footer] is true, the filename
# will appear on the left of the footer, otherwise this space will be blank.
# [page_width] and [lines_per_page] are the page dimensions. These affect how
# wide the header and footer are, and where page breaks are automatically
# inserted.

# -----------------------------------------------------------------------------
#        Nothing needs to be changed beyond this point.
# -----------------------------------------------------------------------------

header_size = 3			# Number of lines that the header takes up
footer_size = 1			# Number of lines the footer takes up

# The maximum number of lines that can appear in a document. Page breaks will
# automatically occur at this boundary.
max_line_count = lines_per_page - (header_size + footer_size)

# Global Variables with their default values.
current_page_number = 1
page_total = 1

import sys

def output_page_header():
	# First, Generate the === and --- lines for the header
	lineA = ""
	lineB = ""
	for i in range(1,page_width):
		lineA += "="
		lineB += "-"
	# And print the first one
	print lineA
	
	
	# Now we need to calculate the spacing for the title line
	page_ID = str(current_page_number) + " of " + str(page_total)
	spaces_needed = page_width - (len(current_page_title) + len(page_ID))
	
	# And now we must build and print the title line
	title_line = current_page_title
	for i in range(1,spaces_needed):
		title_line += " "
	title_line += page_ID
	print title_line
	
	# Finally, print the second header line (---
	print lineB
	
def output_page_end():
	# First build the line
	page_number_line = "page " + str(current_page_number)
	if (filename_in_footer):
		spaces_needed = page_width - (len(page_number_line) + len(filename))
	else:
		spaces_needed = page_width - len(page_number_line)
	for i in range(1,spaces_needed):
		page_number_line = " " + page_number_line
	
	# Then print it out along with the form feed character	
	if (filename_in_footer):
		print filename + page_number_line + ""
	else:
		print page_number_line + ""
	
def output_file_end():
	# First build the line
	line = "END OF FILE"
	spaces_needed = page_width - len(line)
	for i in range(1,spaces_needed):
		line = " " + line
	# Then print it out along with the form feed character
	print line
	
def page_break(line_number):
	global current_page_number
	# If we are on the last page then we should output the EOF stuff.
	# Otherwise, we should output the page end stuff and then the page
	# header for the next page.
	
	# If we arent at the maximum line number, we need to output some empty
	# lines.
	for i in range(line_number, max_line_count):
		print ""
	
	# If we are at the end of the file, print the end of file message
	if (current_page_number == page_total):
		output_file_end()
	# Otherwise, output the footer and then the header for the next page
	else:
		output_page_end()
		# Finally, increment the page number
		current_page_number += 1		
		output_page_header()
	
def count_pages():
	global page_total
	# Open the file
	input = open(filename,'r')
	curlin = input.readline()
	
	# Count the blocks of max_line_count and page breaks
	line_number = 0
	page_number = 0
	while curlin:
		# Dont count control lines
		if (not curlin.startswith("!@#/")):
			line_number += 1
		
		# If we hit max_line_count or a page break, increment the page
		# count.
		if ((line_number == max_line_count) or
			(curlin.startswith("!@#/page-break"))):
			line_number = 0
			page_number += 1
		curlin = input.readline()
		
	# If the last page is not a full page, it wont be counted by the above
	# code, so increment the page number here.
	if (line_number > 0 and line_number < max_line_count):
		page_number += 1	
	
	# Set the page count and close the file
	page_total = page_number
	input.close()
	
def output_file():
	global current_page_title
	global current_page_number
	input = open(filename, 'r')
	curlin = input.readline()
	
	if (curlin.startswith("!@#/title=")):
		current_page_title = curlin.partition("=")[2]
		current_page_title = current_page_title.replace("\n","")
		current_page_title = current_page_title.replace("\r","")
	
	# Now print the page header
	output_page_header()
	
	line_number = 0
	while curlin:
		if (curlin.startswith("!@#/title=")):
			# Set the page title here
			a = 0
		else: 
			# Should we do a page break?
			if (curlin.startswith("!@#/page-break") or
				line_number == max_line_count):
				
				# Do a page break.
				page_break(line_number)
				
				# And reset the line number
				line_number = 0
			else :
				# Output the line and increment the line number
				curlin = curlin.replace("\n","")
				curlin = curlin.replace("\r","")
				print curlin
				line_number += 1
		
		curlin = input.readline()
		
	# If the final page was not a full page, to the final line break
	if (line_number > 0 and line_number < max_line_count):
		page_break(line_number)

def get_args():
	arg_string = ""
	i = 0
	argc = len(sys.argv) - 1
	for arg in sys.argv:
		if i != 0:
			arg_string = arg_string + arg
		if (i != argc) and (i > 0):
			arg_string = arg_string + ' '
		i = i + 1
	return arg_string

# Ok, time to actually do the job.

# We must:
#  0. Process Args, etc.
#  1. Count the pages
#  2. output the file with page numbers, headers, etc.

if len(get_args()) > 0:
	filename = get_args()

if (len(filename) == 0):
	print "Usage: print-format [filename]"
	exit(1)

count_pages()
output_file()