//////////////////////////////////////////////////////////////////////////
//                                                                      //
//  MODULE: HardcopyWriter          AUTHOR: Tim Sabin                   //
//  DESCRIPTION: HardcopyWriter allows the user to write to a printer.  //
//  DATE CREATED: 07/31/1998        LAST UPDATED: 07/31/1998            //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

import java.awt.*;
import java.io.*;
import NoPrintjobException;

public class HardcopyWriter extends Writer {
    private PrintJob job;
    private Font font;
    private int pageDPI;
    private Dimension pagesize;
    private int lineHeight, charWidth, lineAscent;
    private int x0, y0, width, height, linesPerPage;
    private Graphics page;
    private int charNum = 0, lineNum = 0;
    private int pageNum = 0, charsPerPage;
    public HardcopyWriter (Frame frame, double leftMargin,
      double rightMargin, double topMargin, double bottomMargin) 
      throws NoPrintjobException {
        // Get the print job
        Toolkit toolkit = frame.getToolkit ();
        job = toolkit.getPrintJob (frame, "nada", null);
        if (job == null) {
            // User cancelled job! Exception time!
            throw new NoPrintjobException ("User cancelled print job.");
        }
        // Get the page dimensions in pixels
        pageDPI = toolkit.getScreenResolution ();
        pagesize = new Dimension ((int)(8.5 * pageDPI), 11 * pageDPI);
        // Set font to Courier New - plain - 8
        font = new Font ("Courier New", Font.PLAIN, 8 * pageDPI / 72);
        lineHeight = toolkit.getFontMetrics (font).getHeight ();
        charWidth = toolkit.getFontMetrics (font).charWidth ('0');
        lineAscent = toolkit.getFontMetrics (font).getAscent ();
                // Windows wants pixels for it's font
        x0 = (int)(leftMargin * pageDPI);
        y0 = (int)(topMargin * pageDPI);
        // How many lines will fit per page?
        width = pagesize.width - (int)((leftMargin+rightMargin)*pageDPI);
        height = pagesize.height - (int)((topMargin+bottomMargin)*pageDPI);
        linesPerPage = height / lineHeight;
        charsPerPage = width / charWidth;
    }
    public void write (char[] buffer, int index, int len) {
        // DO FOR the length of the buffer
        int i, j;
        for (j = index; j < (index + len); j = i) {
            // DO FOR the printable buffer
            for (i = j; i < (index + len); i++) {
                // Look for substrings not including newline char
                if (buffer [i] == '\n') break;
                if (buffer [i] == '\r') break;
            // ENDDO
            }
            // Print the substring
            print (buffer, j, i - j);
            // Go to the next line IF this was a newline
            if ((i < len) && (buffer [i] == '\n')) {
                newline ();
            }
            i++;
        // ENDDO
        }
    }
    private void print (char[] buffer, int index, int len) {
        if (len == 0) return;
        // Place the passed characters properly on the page
        if (page == null)
            newPage ();
        page.drawChars (buffer, index, len, x0 + charNum * charWidth,
          y0 + (lineNum * lineHeight) + lineAscent);
        charNum += len;
    }
    public void flush () {/* do nothing */}
    private void newline () {
        // Go to a new line. If this line is on a new page, eject and
        // start a new page.
        charNum = 0;
        lineNum++;
        if (lineNum >= linesPerPage) {
            newPage ();
        }
    }
    public void newPage () {
        // IF there is a current page THEN
        if (page != null) {
            // Print the page number and eject
            printPageNo ();
            page.dispose ();
        // ENDIF
        }
        // Start a new page
        page = job.getGraphics ();
        lineNum = 0; charNum = 0;
        pageNum++;
        page.setFont (font);
    }
    private void printPageNo () {
        // Print the page number on the last line, centered
        int firstChar = (charsPerPage / 2) + 10;
        page.drawString ("Page " + pageNum, x0 + (firstChar * charWidth),
          y0 + ((linesPerPage - 22) * lineHeight) + lineAscent);
    }
    public void close () {
        if (page != null) {
            printPageNo ();
            page.dispose ();
            job.end ();
        }
    }
    public int getCharactersPerLine () {
        return linesPerPage;
    }
    public int getLinesPerPage () {
        return linesPerPage;
    }
}
