/* General Text Print Class to output text to a printer.
   Mark Solinski, The Whitewater Group
 */!!

inherit(Printer, #TextPrinter, #(xMax    /* Max columns */ 
xPos    /* Current x position */
yMax    /* Max Rows */
yPos    /* Current y position */
textMetrics
chStr
), 2, nil)!!

now(TextPrinterClass)!!

now(TextPrinter)!!

/* closes down the print document */
Def finish(self)
{ ^eof(self)
}!!

/* create a new document with the passed name */
Def start(self, docName | xtemp, ytemp, lpPt, aPt)
{ Call GlobalCompact(-1);
  if getPrinterParms(self) cand createDC(self)
  then setDocName(self, docName);
    Call GetTextMetrics(hPrintDC, textMetrics);
    aPt := getPhysPageSize(self);
    xtemp := x(aPt);
    ytemp := y(aPt);
    aPt := getPrintingOffset(self);
    xtemp := xtemp - x(aPt);
    ytemp := ytemp - y(aPt);
    xMax := xtemp - 1L;
    yMax := ytemp - 1L;
    if not(startDoc(self))
    then deleteContext(self);
      ^nil;
    endif;
    ^self
  endif;
  ^nil
}!!

/* returns the width in pixels of the passed string
   in the current font */
Def textPixelWidth(self, aStr | aPt)
{ aPt := asPoint(Call GetTextExtent(errorIfNil(hPrintDC, #printerError), lP(aStr), size(aStr)));
  freeHandle(aStr);
  ^x(aPt)
}!!

/* print the object string out to printer, with CR_LF at end */
Def printLine(self, object)
{ print(self, object);
  eol(self);
}!!

/* print the object string out to printer */
Def print(self, object | aStrm, aStr, extent)
{ aStrm := streamOver("");
  printOn(object, aStrm);
  aStr := aStrm.collection;
  if xPos + (extent := textPixelWidth(self, aStr)) > xMax
  then eol(self);
  endif;
  drawString(self, aStr);
  xPos := xPos + extent;
}!!

Def testForNewPage(self)
{ if yPos >= yMax
  then newPage(self);
  endif;
}!!

/* return the tmWidth */
Def  width(self)
{ ^asInt(wordAt(textMetrics, 10));
}!!

/* return the tmHeight */
Def  height(self)
{  ^asInt(wordAt(textMetrics, 8))
  + asInt(wordAt(textMetrics, 0));
}!!

Def eol(self)
{ xPos := 0;
  yPos := yPos + height(self);
  testForNewPage(self);
}!!

/* Reset the x and y position variables  */
Def home(self)
{ xPos := yPos := 0
}!!

/* Draw a string to the printer. */
Def drawString(self, aStr)
{ Call TextOut(errorIfNil(hPrintDC, #printerError), x(self), y(self), lP(aStr),
  size(aStr));
  freeHandle(aStr);
  ^aStr
}!!

/* Home the cursor position and perform a new frame */
Def newPage(self)
{ home(self);
  ^newFrame(self);
}!!

/* Translate yPos and return current y coordinate in
  pixels.  */
Def y(self)
{ ^yPos + 2
}!!

/* Translate xPos and return current x coordinate in
  pixels.  */
Def x(self)
{ ^xPos + 2
}!!

/* Draw a character in the window at current position.
  Go the next line if character is a CR. */
Def drawChar(self, aChar)
{ if aChar == CR
  then ^eol(self)
  endif;
  chStr[0] := max(aChar, ' ');
  Call TextOut(errorIfNil(hPrintDC, #printerError), x(self), y(self), lP(chStr), 1);
  freeHandle(chStr);
  ^aChar
}!!

/* Initialize the text printer class */
Def init(self | xtemp, ytemp, lpPt, aPt)
{ chStr := " ";
  home(self);
  textMetrics := new(Struct, 32);
}!!
