//==============================================================================
// ASALineWriter.java
//==============================================================================
package tribble.io;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PushbackInputStream;
import java.io.Writer;
import java.lang.ArrayIndexOutOfBoundsException;
import java.lang.Exception;
import java.lang.Integer;
import java.lang.NullPointerException;
import java.lang.Object;
import java.lang.String;
import java.lang.System;
import java.lang.Throwable;
/*******************************************************************************
* ASA line printer output stream.
* These methods interpret ASA (ANS) printer form control characters in the first
* column of each output line.
*
*
* ASA (ANS) printer form control characters perform some action affecting the
* position of the logical printing mechanism prior to printing the remaining
* contents of line. The control characters are:
*
*
*
*
* Char |
* Action |
* ASCII Equivalent |
*
*
* 1 |
* Advance the page (form feed) |
* FF |
*
*
* space |
* Advance one line | CR LF
*
*
* 0 |
* Advance two lines | CR LF CR LF
*
*
* - |
* Advance three lines | CR LF CR LF CR LF
*
*
* + |
* Do not advance any lines, overprint the previous line |
* CR |
*
*
*
*
*
* In place of CR LF sequences to advance to the next line,
* the native newline character sequence is used (which could be CR,
* CR LF, or LF sequences).
*
*
*
* The output methods are synchronized, so that when multiple threads write text
* lines to the same line printer stream, each line is written atomically.
* The resulting output will contain interspersed output lines, with no split or
* incomplete lines.
*
*
*
* Source code
*
*
* david.tribble.com/src/java/tribble/io/ASALineWriter.java
* david.tribble.com/src/java.
*
*
*
*
* @version $Revision: 1.2 $ $Date: 2007/12/16 05:25:00 $
* @since API 1.0, 2007-12-12
* @author David R. Tribble (david@tribble.com).
*
* Copyright ©2007 by David R. Tribble, all rights reserved.
* Permission is granted to any person or entity except those designated
* by the United States Department of State as a terrorist, or terrorist
* government or agency, to use and distribute this source code provided
* that the original copyright notice remains present and unaltered.
*
*/
public class ASALineWriter
{
/** Revision information. */
static final String REV =
"@(#)tribble/io/ASALineWriter.java $Revision: 1.2 $ $Date: 2007/12/16 05:25:00 $\n";
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Constants
/** Platform-specific end-of-line (newline) character sequence. */
private static final String EOLN =
System.getProperty("line.separator");
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Static methods
/***************************************************************************
* Convert an ASA printer file into ASCII.
*
* @since 1.2, 2007-12-15
*/
public static void main(String[] args)
throws IOException
{
ASALineWriter out;
int recLen = 80;
char[] buf;
int i;
// Check command line options
for (i = 0; i < args.length && args[i].charAt(0) == '-'; i++)
{
if (args[i].equals("-r"))
recLen = Integer.parseInt(args[++i]);
else
throw new IOException("Bad command option: '" + args[i] + "'");
}
// Check command line args
if (i >= args.length)
{
System.out.println("Convert an ASA printer file into ASCII.");
System.out.println();
System.out.println("usage: java "
+ ASALineWriter.class.getName()
+ " [-option...] file...");
System.out.println();
System.out.println("Options:");
System.out.println(" -r num "
+ "Fixed input record length (default is 80)");
System.exit(255);
}
// Open the output stream
out = new ASALineWriter(
new BufferedWriter(new OutputStreamWriter(System.out)));
buf = new char[recLen];
// Process input files
for ( ; i < args.length; i++)
{
PushbackInputStream in;
// Process the next filename
in = new PushbackInputStream(new FileInputStream(args[i]));
for (;;)
{
int len;
// Read a printer text line
len = readLine(in, buf);
if (len < 0)
break;
// Write the line to the output stream
out.writeLine(buf, 0, len);
}
// Done
in.close();
}
// Clean up
out.close();
}
/***************************************************************************
* Read a fixed-length text line from a printer file.
* This is a helper method for {@link #main main()}.
*
* @since 1.2, 2007-12-15
*/
private static int readLine(PushbackInputStream in, char[] buf)
throws IOException
{
int len;
// Read a printer text line
len = 0;
while (len < buf.length)
{
int ch;
ch = in.read();
if (ch < 0)
{
if (len < 1)
return (-1);
break;
}
if (ch == '\r')
{
ch = in.read();
if (ch != '\n')
in.unread(ch);
break;
}
else if (ch == '\n')
break;
else
buf[len++] = (char) ch;
}
return (len);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Variables
/** Output stream. */
private Writer m_out;
/** Lock object. */
private Object m_lock;
/** Lines written. */
private int m_nLines;
/** Pages written. */
private int m_nPages;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Constructors
/***************************************************************************
* Constructor.
*
* @param out
* Underlying output stream.
* All I/O operations will synchronize on this object.
*
* @throws NullPointerException (unchecked)
* Thrown if out is null.
*
* @since 1.1, 2007-12-12
*/
public ASALineWriter(Writer out)
{
this(out, out);
}
/***************************************************************************
* Constructor.
*
* @param out
* Underlying output stream.
*
* @param lock
* All I/O operations will synchronize on this object.
* This can be null, in which case all I/O operations synchronize on the line
* printer object itself.
*
* @throws NullPointerException (unchecked)
* Thrown if out is null.
*
* @since 1.1, 2007-12-12
*/
public ASALineWriter(Writer out, Object lock)
{
// Sanity checks
if (out == null)
throw new NullPointerException();
if (lock == null)
lock = this;
// Initialize
m_out = out;
m_lock = lock;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Methods
/***************************************************************************
* Finalization.
*
* @since 1.1, 2007-12-12
*/
protected synchronized void finalize()
throws Throwable
{
try
{
close();
}
catch (IOException ex)
{ }
super.finalize();
}
/***************************************************************************
* Close the output stream.
*
* @throws IOException
* Thrown if an I/O write error occurs.
*
* @since 1.1, 2007-12-12
*/
public void close()
throws IOException
{
if (m_out != null)
{
synchronized (m_lock)
{
// Write a final end-of-line to the output stream
if (m_nLines > 0)
m_out.write(EOLN);
// Close the output stream
m_out.close();
}
m_out = null;
m_lock = null;
}
}
/***************************************************************************
* Write any pending output to the output stream.
*
* @throws IOException
* Thrown if an I/O write error occurs.
*
* @since 1.1, 2007-12-12
*/
public void flush()
throws IOException
{
if (m_out == null)
throw new IOException("Output stream is closed");
synchronized (m_lock)
{
m_out.flush();
}
}
/***************************************************************************
* Write a line of characters to the output stream.
* Note that the characters are written as a complete text line, and that the
* first character (line.charAt(0)) is the ASA form control
* character for the line.
*
* @param line
* Text line to write.
* Note that other than the first character, the contents of this line are
* not interpreted. This implies that non-printing characters (especially
* '\n', '\r', and '\f' characters) will produce
* unexpected results.
*
* @throws IOException
* Thrown if an I/O write error occurs.
*
* @since 1.1, 2007-12-12
*/
public void writeLine(String line)
throws IOException
{
// Sanity checks
if (m_out == null)
throw new IOException("Output stream is closed");
// Write the text line to the output stream
if (line.length() < 1)
line = " ";
synchronized (m_lock)
{
writeCtrl(line.charAt(0));
m_out.write(line, 1, line.length() - 1);
m_nLines++;
}
}
/***************************************************************************
* Write a line of characters to the output stream.
* Note that the characters are written as a complete text line, and that the
* first character (line.charAt(off)) is the ASA form control
* character for the line.
*
* @param line
* Text line to write.
* Note that other than the first character, the contents of this line are
* not interpreted. This implies that non-printing characters (especially
* '\n', '\r', and '\f' characters) will produce
* unexpected results.
*
* @param off
* Index of the first character in line to write.
*
* @param len
* Number of characters in line to write.
*
* @throws IOException
* Thrown if an I/O write error occurs.
*
* @since 1.1, 2007-12-12
*/
public void writeLine(String line, int off, int len)
throws IOException
{
// Sanity checks
if (m_out == null)
throw new IOException("Output stream is closed");
if (len < 1)
return;
if (off < 0)
throw new ArrayIndexOutOfBoundsException(off);
if (off+len < 0 || off+len >= line.length())
throw new ArrayIndexOutOfBoundsException(off+len);
// Write the text line to the output stream
synchronized (m_lock)
{
writeCtrl(line.charAt(off));
m_out.write(line, off+1, len-1);
m_nLines++;
}
}
/***************************************************************************
* Write an empty line to the output stream.
*
* @throws IOException
* Thrown if an I/O write error occurs.
*
* @since 1.1, 2007-12-12
*/
public void writeLine()
throws IOException
{
// Sanity checks
if (m_out == null)
throw new IOException("Output stream is closed");
// Write an empty line to the output stream
synchronized (m_lock)
{
writeCtrl(' ');
m_nLines++;
}
}
/***************************************************************************
* Write a line of characters to the output stream.
* Note that the characters are written as a complete text line, and that the
* first character (buf[0]) is the ASA form control character for
* the line.
*
* @param buf
* Characters to write.
* Note that other than the first character, the contents of this line are
* not interpreted. This implies that non-printing characters (especially
* '\n', '\r', and '\f' characters) will produce
* unexpected results.
*
* @return
* The number of characters from buf that were written to the output
* stream.
*
* @throws IOException
* Thrown if an I/O write error occurs.
*
* @since 1.1, 2007-12-12
*/
public int writeLine(/*const*/ char[] buf)
throws IOException
{
return (writeLine(buf, 0, buf.length));
}
/***************************************************************************
* Write a line of characters to the output stream.
* Note that the characters are written as a complete text line, and that the
* first character (buf[off]) is the ASA form control character for
* the line.
*
* @param buf
* Characters to write.
* Note that other than the first character, the contents of this line are
* not interpreted. This implies that non-printing characters (especially
* '\n', '\r', and '\f' characters) will produce
* unexpected results.
*
* @param off
* Index of the first character in buf to write.
*
* @param len
* Number of characters in buf to write.
*
* @return
* The number of characters from buf that were written to the output
* stream.
*
* @throws IOException
* Thrown if an I/O write error occurs.
*
* @since 1.1, 2007-12-12
*/
public int writeLine(/*const*/ char[] buf, int off, int len)
throws IOException
{
int cnt;
// Sanity checks
if (m_out == null)
throw new IOException("Output stream is closed");
if (len < 1)
return (0);
if (off < 0)
throw new ArrayIndexOutOfBoundsException(off);
if (off+len < 0 || off+len >= buf.length)
throw new ArrayIndexOutOfBoundsException(off+len);
// Write the text line characters to the output stream
synchronized (m_lock)
{
writeCtrl(buf[off]);
if (len > 1)
m_out.write(buf, off+1, len-1);
m_nLines++;
}
return (len);
}
/***************************************************************************
* Write an ASA form control character to the output stream.
*
* @param ctl
* ASA form control character.
*
* @throws IOException
* Thrown if an I/O write error occurs.
*
* @since 1.1, 2007-12-12
*/
private void writeCtrl(char ctl)
throws IOException
{
// Interpret the ASA form control character
switch (ctl)
{
case ' ':
default:
// Skip 1 line (single spacing)
if (m_nLines > 0)
m_out.write(EOLN);
break;
case '1':
// Form feed (page eject)
if (m_nLines > 0)
m_out.write(EOLN);
//m_out.flush();
m_out.write('\f');
m_nPages++;
break;
case '0':
// Skip 2 lines
if (m_nLines > 0)
m_out.write(EOLN);
m_out.write(EOLN);
m_nLines++;
break;
case '-':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case 'A':
case 'B':
case 'C':
// Skip 3 lines
if (m_nLines > 0)
m_out.write(EOLN);
m_out.write(EOLN);
m_out.write(EOLN);
m_nLines += 2;
break;
case '+':
// Skip no lines, overstrike the previous line
if (m_nLines > 0)
m_out.write('\r');
break;
}
}
/***************************************************************************
* Retrieve the number of lines written to the output stream.
*
* @return
* Number of lines written to the output stream so far (starting with zero).
*
* @since 1.1, 2007-12-12
*/
public int getLineCount()
{
return (m_nLines);
}
/***************************************************************************
* Reset the line counter for the output stream.
*
* @param n
* Line number at which to begin re-counting.
*
* @since 1.1, 2007-12-15
*/
public void setLineCount(int n)
{
m_nLines = n;
}
/***************************************************************************
* Retrieve the number of pages written to the output stream.
*
* @return
* Number of pages written to the output stream so far (starting with zero).
*
* @since 1.1, 2007-12-12
*/
public int getPageCount()
{
return (m_nPages);
}
/***************************************************************************
* Reset the page counter for the output stream.
*
* @param n
* Page number at which to begin re-counting.
*
* @since 1.1, 2007-12-15
*/
public void setPageCount(int n)
{
m_nPages = n;
}
}
// End ASALineWriter.java