     ////////////////////////////////////
    // TEXT-COLUMNS                    //
   // Written by Andrew Broad         ///
  //                                 ////
 // Columns.java (2003:04:12 19:19) /////
////////////////////////////////////////
// Methods of Columns:             ////
// - static columns                ///
// - static main                   //
////////////////////////////////////

import java.io.*;
import java.util.*;

/*****************************************************************************
** The class `Columns' is for arranging narrow text-files into columns.
*****************************************************************************/

public class Columns {
	/********************************************************************/
	// static Columns.columns : BufferedReader x int x int x int -> void
	/*********************************************************************
	** Outputs a text-file to stdout where the lines in the input file
	** are arranged in columns, padded out with spaces.
	** @param columns The number of columns to generate.
	** @param columnWidth The width (in characters) of each column.
	** @param linesPerPage The number of lines per page, which - if not
	**        specified (0) - defaults to the number of lines in the file
	**        divided by the number of columns.
	*********************************************************************/

	private static void columns (BufferedReader br, int columns,
	                             int columnWidth, int linesPerPage)
	{
		Vector lines= new Vector();
		String line;
		////////////////////////////////////////////
		// Read all lines from file into a vector //
		////////////////////////////////////////////
		try {
			while ((line= br.readLine()) != null) {
				if (line.length() > columnWidth) {
					System.err.println("A column-width of"
					+ " " + columnWidth + " is too narrow"
					+ " for this file.");
					System.exit(1);
				}
				lines.add(line);
			}
		} catch (IOException ioe) {
			System.err.println("Columns.columns: IOException"
			+ " thrown by BufferedReader.readLine()");
			System.exit(1);
		}

		int linesOfOutput= lines.size() / columns;
		if (lines.size() % columns != 0) linesOfOutput++;

		if (linesPerPage == 0) {
			linesPerPage= linesOfOutput;
		} else {
			linesOfOutput+= linesPerPage
			                - (linesOfOutput % linesPerPage);
		}
		////////////////////////////////////////////////////////////
		// Process the vector into an array of strings for output //
		////////////////////////////////////////////////////////////
		String[] output= new String[linesOfOutput];
		for (int n= 0; n < linesOfOutput; n++) {
			output[n]= "";
		}
		ListIterator li= lines.listIterator();
		int i= 0; int c= 0;
		while (li.hasNext()) {
			output[i]+= li.next();
			for (int s= ((output[i].length()-1) % columnWidth)+1;
			     s < columnWidth && c < columns-1; s++)
			{
				output[i]+= " ";
			}
			i++;
			if (i % linesPerPage == 0) {
				c++;
				i-= linesPerPage;
			}
			if (c == columns) {
				i+= linesPerPage;
				c= 0;
			}
		}

		/////////////
		// Output. //
		/////////////
		for (int n= 0; n < linesOfOutput; n++) {
			if (! output[n].equals("")) {
				System.out.println(output[n]);
			}
		}
	}

	/********************************************************************/
	// static Columns.main : String[] -> void
	/*********************************************************************
	** The entry-point of Columns. This program splits a narrow text-file
	** into columns padded out with spaces.
	** @param argv The vector of command line arguments. There should be
	**             at least three of these: the first argument must be the
	**             filename of a text file, the second argument is the
	**             number of columns, the third argument is the width (in
	**             characters) of each column, and the optional fourth
	**             argument is the number of lines per page, which - if
	**             not specified - defaults to the number of lines in the
	**             file divided by the number of columns.
	*********************************************************************/

	public static void main (String argv[]) {
		if (argv.length < 3 || argv.length > 4) {
			System.err.println("Usage: java Columns <filename1.tx"
			+ "t> <number_of_columns> <column-width> (<lines_per_"
			+ "page>)) > <filename2.txt>"
			+ "\n       where filename1.txt != filename2.txt");
			System.exit(1);
		}

		BufferedReader br= null; FileInputStream fis= null;
		try {
			br= new BufferedReader(new InputStreamReader
		                 (fis= new FileInputStream(argv[0])));
		} catch (FileNotFoundException fnfe) {
			System.err.println("Columns.main: FileNotFoundExcepti"
			+ "on for \"" + argv[0] + "\"");
			System.exit(1);
		}

		int columns= 2;
		try {
			columns= Integer.parseInt(argv[1]);
		} catch (NumberFormatException nfe) {
			System.err.println(argv[1] + " doesn't parse as an "
			+ "integer!");
			System.exit(1);
		}

		int columnWidth= 39;
		try {
			columnWidth= Integer.parseInt(argv[2]);
		} catch (NumberFormatException nfe) {
			System.err.println(argv[2] + " doesn't parse as an "
			+ "integer!");
			System.exit(1);
		}

		int linesPerPage= 0;
		if (argv.length >= 4) {
			try {
				linesPerPage= Integer.parseInt(argv[3]);
			} catch (NumberFormatException nfe) {
				System.err.println(argv[3] + " doesn't parse "
				+ "as an integer!");
				System.exit(1);
			}
		}

		columns(br, columns, columnWidth, linesPerPage);

		try {
			fis.close();
		} catch (IOException ioe) {
			System.err.println("FileInputStream.close threw an "
			+ "IOException!");
			System.exit(1);
		}
	}
}
