/******************************************************************************
BufferedOutput extends the BufferedOutputStream by providing the features for
??? need to describe ???

----------------------------------------------------
Copyright (c) Gunnar Gotshalks. All Rights Reserved.

Permission to use, copy, modify, and distribute this software
and its documentation for NON-COMMERCIAL purposes and
without fee is hereby granted. 
******************************************************************************/

package FlexOr.io;
import java.io.*;

public class BufferedOutput extends BufferedOutputStream {

/******************************************************************************
Creating an instance of BufferedOutput opens the named file.  There is
no open required by the user. In the OO paradigm opening a file
is analogous to creating a new object unlike procedural paradigm where
the same variables are reused for each file.
---------------------------*/

public BufferedOutput (String fileName) throws IOException {
  super(new FileOutputStream(fileName));
}

/******************************************************************************
To help users of the output data type keep statistics within application
programs we provide: (1) a count, charCount of the total number of characters
emitted to the output file; and (2) the number of characters output, LineLength,
since the last new line character.
---------------------------*/

private int charCount = 0;
public int getCharCount() { return charCount; }

private int lineLength = 0;
public int getLineLength() { return lineLength; }

/******************************************************************************
The purpose of FlexOr is not to provide full typsetting functionality but it
does have to provide for some.  In place of a completely flexible tab rack
facility, FlexOr provides |Output~TabStopDist| which is a uniform distance
between tab postions.  Tab position would be |1+Output~TabStopDist*n|.
---------------------------*/

  private int tabStopDist;
  public int getTabStopDist() { return tabStopDist; }
  public void setTabStopDist(int tabStopDist){ this.tabStopDist = tabStopDist; }
  
/******************************************************************************
---------------------------*/

public void write(int theChar) {
  if (theChar == Char.EOL) { writeNewline(); return; }
  charCount++;  lineLength++;
  try { super.write(theChar);
  } catch (IOException e) { System.err.println("Cannot write character: " + e); }
}
  
/******************************************************************************
When a new line character is emitted we want to reset lineLength.
Again, having a special purpose parameterless call is more efficient and
descriptive in application programs.
---------------------------*/

public void writeNewline() {
  charCount++; lineLength = 0;
  try { super.write(Char.Newline);
  } catch (IOException e) { System.out.println("Cannot write newline: " + e); }
}
  
/******************************************************************************
---------------------------*/

public void write(byte[] buffer, int offset, int count) {
  charCount += count ; lineLength += count;
  try { super.write(buffer, offset, count);
  } catch (IOException e) { System.out.println("Cannot write buffer: " + e); }
}

/******************************************************************************
Occasionally we need to output to the current line
without adding to the line length (for example, when markup tags are output).
The following operation prints directly to the output file.  The total number
of output characters is incremented but the line length is not.
---------------------------*/

public void writeNoCount(byte[] buffer, int offset, int count) {
  charCount += count;
  try { super.write(buffer, offset, count);
  } catch (IOException e) { System.out.println("Cannot write buffer: " + e); }
}

/******************************************************************************
We make use of the standard Java conversion routine combined with our custom
output of strings.
---------------------------*/

public void writeInteger(int integer) {
  String intString = String.valueOf(integer);
  byte[] buffer = intString.getBytes();
  write(buffer, 0, intString.length());
}

/******************************************************************************
Require: String.valueOf(integer).length <= width

Output an integer in a specified width of field.
---------------------------*/

public void writeInteger(int integer, int width) {
  String intString = String.valueOf(integer);
  byte[] buffer = intString.getBytes();
  int length = intString.length();
  int pad = width - length;
  
  while (pad-- > 0) write(' ');
  write(buffer, 0, length);
}
}