TweetFollow Us on Twitter

TReportPrint
Volume Number:9
Issue Number:6
Column Tag:MacApp Workshop

Related Info: Print Manager

TReportPrinter

A supplemental printing class for MacApp

By William L. Colsher, Minneapolis, Minnesota

Note: Source code files accompanying article are located on MacTech CD-ROM or source code disks.

About the author

William L. Colsher, 5400 3rd Avene South. Minneapolis, Minnesota 55419.

Background

MacApp is, without question, the most comprehensive commercially available class library for the Macintosh. And to a large extent it fulfills its rather ambitious goal of providing a complete Macintosh application framework. But no class designer can anticipate every use to which his work will be put. He must produce a set of general purpose classes that are easily subclassed to provide specific behavior yet still contain enough functionality to be worth using. Nowhere is this more evident than in MacApp’s printing architecture.

One of the fundamental assumptions built into MacApp is the relationship between a document (represented by a subclass of TFileBasedDocument) and the presentation of that document’s data (by the many subclasses of TView). Specifically, it is assumed that some combination of TView objects will be able to present the document’s data both on screen and when that data is printed. As a consequence, MacApp’s printing class TStdPrintHandler depends on a document’s TView objects to draw the data on the selected printer.

This is a reasonable and powerful assumption. It takes advantage of QuickDraw’s ability to draw in any GrafPort regardless of whether that GrafPort represents a window, a printer, a buffer in RAM, or something we haven’t yet imagined. It also greatly simplifies the creation of WYSIWYG style applications. For some documents this is ideal. To print one simply attaches a TStdPrintHandler or a subclass of it to the TView to be printed. This TView need not be the same view used to display the document on screen. Nevertheless, it must be a subclass of TView.

In many cases that assumption is perfectly valid. But for a large class of real-world applications, the TView/TStdPrintHandler approach is unnecessarily (even hopelessly) complex. These are the applications that must print reports. Boring though they may be to program, printed reports are the lifeblood of modern business. The problem with reports (from the standpoint of MacApp’s printing architecture) is that it is often impossible to predict their length or exact form without first processing all the data that is to be printed. While it is possible to create views “on the fly” to represent a printed report, it is often impractical. The process is complex and time consuming at best. The data must be processed at least twice (once to build the views, then again to print them). Unless they are very carefully designed, the TView subclasses will tend to multiply uncontrollably as reporting requirements change. And, perhaps most important from an object programming point of view, the data objects lose control of a very important piece of functionality: their own printing.

TReportPrinter attempts to provide an alternative to MacApp’s built in printing architecture that addresses just this problem. TReportPrinter’s goal is to encapsulate the Macintosh printing process in a way that makes it easy for an application to format and print text oriented reports. It effectively hides the often poorly understood mechanics of the Macintosh Printing Manager, leaving the well understood process of formatting report lines to the document and it’s data objects.

Overview of TReportPrinter

The structure of TReportPrinter corresponds quite closely to that of the traditional Macintosh “printing loop”. Its fields contain the various pointers required by the Printing Manager and its methods implement the many steps required to print the lines and pages of a report and to provide an adequate safety net should something go wrong. In addition there are methods that provide control of print characteristics (font, size, etc.), pagination, and the printing of headers and footers. The rest of this section explains the function of each field and method of TReportPrinter in some detail. They are documented in alphabetical order for easy reference, Their usage is documented in the next section: Using TReportPrinter.

Fields:

Boolean fAutoFormFeed - TRUE if TReportPrinter is to start a new page whenever fBottomOfPage will be passed by the next print operation.

short fBottomOfPage - Stores the highest location (in pixels) to be printed on a page. It may not be greater than the length of the page in pixels.

short fCurrentFace - Store the current font’s “face” (i.e. bold, italic, etc.).

CStr255 fCurrentFontName - Stores the name of the font currently used for printing. It is provided for the convenience of subclasses.

short fCurrentFontNumber - Stores the number of the current printing font.

short fCurrentPage - A convenience for subclasses that need to print page numbers.

short fCurrentSize - Stores the current font’s size.

short fLeftMargin - The left margin location in pixels, offset from zero.

long fMaxSpoolLines - The maximum number of lines that the Printing Manager can spool to disk. It is calculated in IReportPrinter().

TReportStatusWindow fMyStatusWindow - Reference to the modal status window TReportPrinter creates when starting a report. This window is responsible for intercepting Cmd-. It may display any status message.

long fPrintedLines - The number of lines that have been printed. Used with fMaxSpoolLines to determine when to close the Printing Manager “document” and start a new one.

TPPrPort fPrintingPort - Pointer to the Printing Manager TPPrPort being used for printing.

Boolean fPrintManagerIsOpen - There are two methods where TReportPrinter might open the Printing Manager with a call to PrOpen(). However, it is important to do this only once. It is set to TRUE when PrOpen() is called.

THPrint fPrintRecord - Handle to the Printing Manager “print record” currently in use.

CStr255 fReportTitle - Displayed in the status window, this field is usually the parent document’s name. It does not have to be however. It also may be a convenience when printing headers or footers.

Boolean fUserAborted - Set to TRUE if a user hits Cmd-.

Methods:

pascal void DoClosePage(void) - DoClosePage() encapsulates PrClosePage(). Rarely called by the user of TReportPrinter.

pascal void DoFormFeed(void) - DoFormFeed() calls PrintFooter(), advances to the top of the next page (by calling DoClosePage() and DoOpenPage()) and then calls PrintHeader().

pascal Boolean DoOpenPage(void) - DoOpenPage() encapsulates PrOpenPage(). Rarely called by the user of TReportPrinter. (Call DoFormFeed() instead.)

pascal void DoPrClose(void) - Calls PrClose(), sets fPrintManagerIsOpen to false, frees the print record and closes the status window if it exists. Not normally called by the user of the class.

pascal void DoPrOpen(void) - Calls PrOpen() and allocates a print record if necessary. Sets fPrintManagerIsOpen to true. Not normally called by the user of the class.

pascal void EndReport(void) - Call EndReport() when your printing is finished. It closes the current page and print document, then calls the appropriate Print Manager routines to “print” your report.

pascal void Free(void) - Call this method from you document’s Free() method.

pascal unsigned long GetFreeSpaceOnDisk(int theVolume) - Used internally to determine how large a document we can “spool”.

pascal Boolean HandlePageSetup(void) - Call HandlePageSetup() in response to a cPageSetup command in your document’s DoMenuCommand() method.

pascal void IReportPrinter(CStr255 theFont, 
 short theFace, 
 short theSize, 
 short leftMargin, 
 short bottomOfPage,
 Boolean autoFormFeed);

IReportPrinter() sets the initial parameters for printing. Notice that the font to be used is specified by its name. theFace and theSize are specified as you would for QuickDraw. The two margin arguments are specified in pixels. If autoFormFeed is true, TReportPrinter will advance to the next page whenever a “line feed” operation would cause the next line to print beyond bottomOfPage

pascal Boolean PrintALine(CStr255 theLine, 
 Boolean doLineFeed);

PrintALine() prints the contents of theLine. If doLineFeed is true, it also advances the cursor to the logical next line.

pascal void PrintFooter(void) - Override this method to print your page footer.

pascal void PrintHeader(void) - Override this method to print your page header.

pascal void SetDocumentName(Str255 docName) - Used to tell TReportPrinter the name of the document being printed. TReportPrinter passes this information on to the status window.

pascal void SetFace(short theFace);

pascal void SetFont(CStr255 theFont);

pascal void SetSize(short theSize);

These three methods set the face, font, and size that will be used for printing. These methods must be called after a DoOpenPage() to work correctly.

pascal Boolean StartReport(CmdNumber aCmdNumber) - StartReport() opens the print manager, calls PRJobDialog() and instantiates the status window. It also verifies that the bottom margin does not exceed the size of the paper. (If it does, the bottom margin is set to the bottom of the printing GrafPort.)

pascal void UserAbort(void) - Called by the status window if the user hits Cmd-.

pascal void VerticalTab(short pixels) - Advances the cursor down the current page by pixels. It will cross page boundaries in the obvious way.

Using TReportPrinter

Incorporating TReportPrinter into your program is a straightforward task. The first step is to create an instance of TReportPrinter and initialize it. This is typically done in your document’s initialization method and requires only two lines (all these examples are from the demonstration program available on the source code disk):

/* 1 */

fMyReportPrinter= new TReportPrinter;
fMyReportPrinter->IReportPrinter(“\pmonaco”,// Font
 normal,   // Face
 9,      // Size
 36,     // Left margin
 648,    // Bottom Margin
 false); // no auto-FF

Of course you will also have to respond to menu commands. In your document’s DoMenuCommand( ) method, the following lines handle all that is necessary:

/* 2 */

case cPageSetup:
 fMyReportPrinter->HandlePageSetup();
 break;

case cPrint:
 GetInspectorName(docName); // get this document’s name
 fMyReportPrinter->SetDocumentName(docName); 
 if(fMyReportPrinter->StartReport(aCmdNumber)) {
 fMyReportPrinter->PrintHeader();
 
// Your code to feed lines to the report printer goes here
 
 fMyReportPrinter->EndReport();
 }
 break;

Except in very simple cases (such as the demo program that accompanies this article) it is probably preferable to create and post a command to handle the cPrint case. This better fits the object way of life by isolating your printing code from parts of the program that really have no business knowing about printing. It will also make it easier to create new “reporting” objects as your users’ needs change.

Some Interesting Things To Note

Because TReportPrinter is designed to print reports (not documents) it cannot be used to handle things like the “Print Documents” Apple Event without considerable re-writing. This is a fairly straightforward task and while it would be interesting (and perhaps even useful) to complete, I have a full time job and a family to attend to. Therefore, it is left as an exercise for the interested reader. A couple of hints are in order however. First, since TReportPrinter makes many calls to gApplication->PollEvent( ) it will be necessary to change the global event mask to ignore Apple Events. This is because two Apple Events are sent when a user Prints from the finder: the Print Document event with its list of documents to be printed and a Quit event. Rather obnoxiously (but necessarily) it sends them “back to back”. So... if your application continues to process Apple Events while the Finder is printing, it will quit in the middle of printing the first document.

The second hint involves handling multiple print jobs. TReportPrinter assumes that it will be printing one report at a time and that a user will select “Page Setup” if necessary. When Finder Printing, one normally provides the “Page Setup” and “Print” dialogs only once, preserving a copy of the print record (a THPrint named fPrintRecord in TReportPrinter) for use in each subsequent print job. I would be very interested in hearing from anyone who manages these modifications. Although I don’t have a use for the class today, one never knows what’s just around the corner.

Users of other application frameworks and class libraries have probably noted that TReportPrinter is descended from TObject, MacApp’s base class. There is actually nothing in TReportPrinter that requires this. Converting it for use with another system should involve little more than changing the base class, replacing calls to PollEvent( ) with their equivalent, and modifying the way a user abort is handled to fit the library being used. TReportPrinter also makes fairly extensive use of MacApp’s error handling mechanism and that code too would have to be changed.

Finally, although TReportPrinter has been used quite heavily in a couple of commercial applications, it has been slightly modified for this article. And, while I have tested it, that is no reason to assume that it is completely bug free. If you do encounter bugs, I’ll be interested to hear from you. The best way to contact me is writing the address at the beginning of this article. I can also be contacted on AppleLink at SKAMP.


Listing: TReportPrinter.h

#ifndef __REPORTPRINTER__
#define __REPORTPRINTER__ 1
#include <Printing.h>

const short kStatusWindowView = 2000;
const IDTypekDocumentNameID = ‘VW08’;

class TReportStatusWindow;

class TReportPrinter: public TObject {
private:
 BooleanfPrintManagerIsOpen;
public:
 CStr255fCurrentFontName;
 short  fCurrentFontNumber;
 
 long   fMaxSpoolLines;
 long   fPrintedLines;

 
 short  fCurrentFace;
 short  fCurrentSize;
 short  fLeftMargin;
 short  fBottomOfPage;
 BooleanfAutoFormFeed;
 BooleanfUserAborted;
 
 TPPrPort fPrintingPort;  // a pointer
 THPrintfPrintRecord;// a handle
 
 TReportStatusWindow *fMyStatusWindow;
  
 short  fCurrentPage;
 CStr255fReportTitle;

 virtual pascal void IReportPrinter(CStr255 theFont,
 short theFace, short theSize, 
 short leftMargin, short bottomOfPage,
 Boolean autoFormFeed);
 virtual pascal void DoPrOpen(void);
 virtual pascal void DoPrClose(void);
 virtual pascal void SetFont(CStr255 theFont);
 virtual pascal void SetFace(short theFace);
 virtual pascal void SetSize(short theSize);
 virtual pascal Boolean 
 StartReport(CommandNumber aCmdNumber);
 virtual pascal Boolean   PrintALine(const CStr255 theLine,
 Boolean doLineFeed);
 virtual pascal void DoFormFeed(void);
 virtual pascal Boolean   DoOpenPage(void);
 virtual pascal void DoClosePage(void);
 virtual pascal void VerticalTab(short pixels);
 virtual pascal void EndReport(void);
 virtual pascal Boolean   HandlePageSetup(void);
 virtual pascal void PrintHeader(void);
 virtual pascal void PrintFooter(void);
 virtual pascal void Free(void);
 virtual pascal unsigned long
 GetFreeSpaceOnDisk(int theVolume);
 virtual pascal void UserAbort(void);
 virtual pascal void SetDocumentName(CStr255 docName);
};

class TReportStatusWindow: public TWindow {
public:
 virtual pascal void
 IReportStatusWindow(TReportPrinter *myPrinter);
 virtual pascal void DoCommandKeyEvent(TToolboxEvent* event);
 virtual pascal void SetMessage(CStr255 theMessage);
private:
 TReportPrinter *fMyPrinter;
};

#endif
Listing: TReportPrinter.cp

#include <MacApp.h>
#include <Fonts.h>
#include “TReportPrinter.h”

//•••••• TReportPrinter ••••••

#pragma segment PrintInit
pascal void TReportPrinter::IReportPrinter(CStr255 theFont, 
 short theFace, 
 short theSize, 
 short leftMargin, 
 short bottomOfPage,
 Boolean autoFormFeed)
{
 short  theFontNumber;
 
 fPrintRecord = nil;
 fPrintingPort = nil;
 fMyStatusWindow = nil;
 
 // true if we handle formfeeds
 fAutoFormFeed = autoFormFeed;
 
 // initialize the font/face/size fields
 
 fCurrentFontName = theFont;
 GetFNum(theFont, theFontNumber);  
 
 fCurrentFontNumber = theFontNumber;
 fCurrentFace = theFace;
 fCurrentSize = theSize;
 
 fBottomOfPage = bottomOfPage;
 fLeftMargin = leftMargin;
 fUserAborted = false;
 fMyStatusWindow = nil;
 fPrintedLines = nil;
 fCurrentPage = nil;
 fPrintManagerIsOpen = false;
 
 // GetFreeSpaceOnDisk returns a value in multiples of 1024. 
 // We can only use half the space since the print manager 
 // spool file and a background print file of the same size 
 // might exist at the same time.  Then, If we have 80 
 // character lines, we’ll get about 12 of them 
 // per 1024 bytes. 
 
 short  theVol;
// get default volume ref. number
 OSErr  err = GetVol(0,theVol);    
 long   maxSpoolLines = 
 (GetFreeSpaceOnDisk(theVol) / 2) * 12;
 fMaxSpoolLines = maxSpoolLines;
}

#pragma segment PrintOpen
pascal void TReportPrinter::DoPrOpen(void)
{
 FailInfo fi;
 THPrintaPrintRecord = nil;
 
 VOLATILE(aPrintRecord);
 
 if(fi.Try()) {
 if(!fPrintManagerIsOpen) { // open only if necessary
 PrOpen();
 
 // Allocate and initialize a print record if necessary
 if(fPrintRecord == nil) {
 aPrintRecord = (THPrint)NewHandle(sizeof(TPrint));
 PrintDefault(aPrintRecord);// Set “standard” values
 fPrintRecord = aPrintRecord;
 }
 fPrintManagerIsOpen = true;
 }
 fi.Success();
 }
 else {
 fPrintManagerIsOpen = false;
 if(fPrintRecord) {
 DisposeHandle((Handle)fPrintRecord);
 fPrintRecord = nil;
 }
 PrClose();
 fi.ReSignal();
 }
}

#pragma segment PrintOpen
pascal void TReportPrinter::SetDocumentName(CStr255 theDoc)
{
 fReportTitle = theDoc;
}

#pragma segment PrintMain
pascal void TReportPrinter::Free(void)
{
 if(fPrintRecord) {
 DisposeHandle((Handle)fPrintRecord);
 fPrintRecord = nil;
 }
 // fPrintingPort should have been freed and set to 0 by the 
 // PrCloseDoc call in EndReport(). But just to be on 
 // the safe side...
 
 if(fPrintingPort) { 
 PrCloseDoc(fPrintingPort);
 fPrintingPort = nil;
 }
 
 if(IsObject(fMyStatusWindow))
 fMyStatusWindow->Close();
 
 inherited::Free();
}

#pragma segment PrintMain
pascal Boolean TReportPrinter::HandlePageSetup(void)
{
 //Note: The TReportPrinter MUST be initialized before 
 // allowing a call to this method.
 
 Booleanrc = false;
 DoPrOpen();// open the print manager if necessary
 if(fPrintRecord) {
 rc = PrStlDialog(fPrintRecord);
 }
 return rc;
}

#pragma segment PrintOpen
pascal Boolean TReportPrinter::StartReport(
 CommandNumber/* aCmdNumber*/)
{
 // display the Job Dialog and if it returns true, open the 
 // print port and then open the first page.
 
 FailInfo fiWindow, fiPrint;
 Boolean  doIt = false;
 TReportStatusWindow *aStatusWindow = nil;
 TPPrPort aPrintingPort = nil;

 VOLATILE(aStatusWindow);
 
 if(fiPrint.Try()) {
 DoPrOpen();// open the print manager if necessary
 
 fCurrentPage = 0;
 fPrintedLines = 0;
 fUserAborted = false;
 
 doIt = PrJobDialog(fPrintRecord); 
 
 if(doIt && PrError() == noErr) {
 
 // first we try to open the print document
 
 aPrintingPort = PrOpenDoc(fPrintRecord, 0, 0);
 fPrintingPort = aPrintingPort;
 
 if(PrError() == noErr) {
 if(fiWindow.Try()) {
 aStatusWindow = (TReportStatusWindow *)
 gViewServer->NewTemplateWindow 
 (kStatusWindowView, 0);
 aStatusWindow->IReportStatusWindow(this);
 aStatusWindow->Open();
 fMyStatusWindow = aStatusWindow;
 fiWindow.Success();
 }
 else {
 fMyStatusWindow = nil;
 fiWindow.ReSignal();
 }

 // let everybody else update, etc.
 gApplication->PollEvent(false); 
 if(DoOpenPage()) {// try to start a page
 doIt = true;    // everything worked!
 
 // verify that the bottom margin does not excede 
 // the capabilities of the printer
 
 if(fBottomOfPage > 
 ((GrafPtr)fPrintingPort)->portRect.bottom)
 fBottomOfPage = 
 ((GrafPtr)fPrintingPort)->portRect.bottom;
 }
 else { // PrOpenPage failed
 doIt = false;
 }
 } 
 else { // PrOpenDoc failed...
 PrCloseDoc(fPrintingPort); // frees fPrintingPort
 fPrintingPort = nil;
 doIt = false;
 }
 }
 else {
 // PrJobDialog() failed or the user hit cancel
 doIt = false; 
 }
 if (!doIt) // finish cleaning up after any failures
 DoPrClose();
 fiPrint.Success();
 }
 else {
 fiPrint.ReSignal();
 }
 return doIt;
}

#pragma segment PrintMain
pascal void TReportPrinter::DoPrClose(void)
{
 PrClose(); // close the print manager (TN 161)
 fPrintManagerIsOpen = false;
 if(fPrintRecord) {// and dispose of the print record
 DisposeHandle((Handle)fPrintRecord);
 fPrintRecord = nil;
 }
 if(IsObject(fMyStatusWindow))
 // has free on closing checked in viewedit
 fMyStatusWindow->Close();
 fMyStatusWindow = nil;
}

#pragma segment PrintMain
pascal void TReportPrinter::EndReport(void)
{
 // Note: This is the simplest possible way to 
 // wrap up a print job.
 TPrStatusstatus;
 
 PrClosePage(fPrintingPort); // ensure current page is closed
 PrCloseDoc(fPrintingPort);  // frees fPrintingPort
 fPrintingPort = nil;
 
 if ((**fPrintRecord).prJob.bJDocLoop == 
 bSpoolLoop && PrError() == noErr) { 
 // let everybody else update, etc.
 gApplication->PollEvent(false);   
 PrPicFile(fPrintRecord,0,0,0,status);
 }
 DoPrClose();  
}

#pragma segment PrintImage
pascal Boolean TReportPrinter::DoOpenPage(void)
{
 // Notes: PrOpenPage completely resets the printing 
 // grafport so it is necessary to set the font, face, 
 // and size every time we do this. 
 
 fCurrentPage++;
 fMyStatusWindow->SetMessage(fReportTitle);
 // let everybody else update, etc.
 gApplication->PollEvent(false);   

 PrOpenPage(fPrintingPort, 0);
 if(PrError() == noErr) {
 TextFont(fCurrentFontNumber);
 TextFace(fCurrentFace);
 TextSize(fCurrentSize);
 return true;
 }
 else {
 PrClosePage(fPrintingPort);// match the cPrOpenPage
 PrCloseDoc(fPrintingPort); // frees fPrintingPort
 fPrintingPort = nil;
 return false;
 }
}

#pragma segment PrintImage
pascal void TReportPrinter::DoClosePage(void)
{
 TPPrPort aPrintingPort = nil;
 FailInfo fi;
 
 VOLATILE(aPrintingPort);
 
 PrClosePage(fPrintingPort);// end the page
 
 if(fPrintedLines > fMaxSpoolLines) {
 EndReport();    // print what we have
 if(fi.Try()) {
 // start a new one
 aPrintingPort = PrOpenDoc(fPrintRecord, 0, 0);
 fPrintingPort = aPrintingPort;
 fi.Success();
 }
 else {
 fPrintingPort = nil;
 fi.ReSignal();
 }
 
 }
 // let everybody else update, etc.
 gApplication->PollEvent(false); 
}

 // Note: The next three methods must be called AFTER
 // DoOpenPage() to have the desired effect.

#pragma segment PrintImage
pascal void TReportPrinter::SetFont(CStr255 theFont)
{
 short  theFontNumber;
 
 fCurrentFontName = theFont;
 GetFNum(theFont, theFontNumber);  
 
 fCurrentFontNumber = theFontNumber;
 
 // actually set the font in the grafport
 TextFont(fCurrentFontNumber);
}

#pragma segment PrintImage
pascal void TReportPrinter::SetFace(short theFace)
{
 fCurrentFace = theFace;
 TextFace(fCurrentFace);
}

#pragma segment PrintImage
pascal void TReportPrinter::SetSize(short theSize)
{
 fCurrentSize = theSize;
 TextSize(fCurrentSize);
}

#pragma segment PrintImage
pascal void TReportPrinter::DoFormFeed(void)
{
 PrintFooter();
 DoClosePage();
 DoOpenPage();
 PrintHeader();
}

#pragma segment PrintImage
pascal void TReportPrinter::PrintHeader(void)
{
 FontInfo theInfo;

 // basic operation only - override for custom header

 GetFontInfo(theInfo);
 MoveTo(fLeftMargin, theInfo.ascent + 
 theInfo.descent + theInfo.leading);
 // don’t forget to increment fPrintedLines
}

#pragma segment PrintImage
pascal void TReportPrinter::PrintFooter(void)
{
 // Override for custom Footer
 // don’t forget to increment fPrintedLines
}

#pragma segment PrintImage
pascal Boolean TReportPrinter::PrintALine(
 const CStr255 theLine, Boolean doLineFeed)
{
 // Note: LineFeeds are done based on the font metrics. 
 // For other size linefeeds use VerticalTab();
  
 CPoint theSpot;
 FontInfo theInfo;
 GrafPtrsavedPort;
 
 if(fUserAborted) {
 PrSetError(iPrAbort);    // let the print manager know
 EndReport();
 return false;
 }
 
 DrawString(theLine);
 if(doLineFeed) {
 fPrintedLines++;
 GetPen(theSpot);
 GetFontInfo(theInfo);
 short verticalPosition = theSpot.v + theInfo.ascent + 
 theInfo.descent + theInfo.leading;
 MoveTo(fLeftMargin, verticalPosition);
 if(verticalPosition >= fBottomOfPage && fAutoFormFeed) {
 DoFormFeed();
 }
 GetPort(savedPort);
 // let everybody else update, etc.
 gApplication->PollEvent(false); 
 SetPort(savedPort); // make sure we’re in the right place
 }
 return true;
}

#pragma segment PrintImage
pascal void TReportPrinter::VerticalTab(short pixels)
{
 CPoint theSpot;
 
 GetPen(theSpot);
 theSpot.v+=pixels;
 if(theSpot.v >= fBottomOfPage) {
 DoFormFeed();
 }
 else
 MoveTo(theSpot.h, theSpot.v);
}

#pragma segment PrintInit
pascal unsigned long TReportPrinter::GetFreeSpaceOnDisk(
 int theVolume)
{
    HVolumeParam HPB;
    OSErr err;
  unsigned long pfreeBytes;
 
    HPB.ioNamePtr = 0L;       
    HPB.ioVRefNum = theVolume;      
    HPB.ioVolIndex = 0;       
    err = PBHGetVInfo((HParamBlockRec *)&HPB,false);
    if (err == noErr)
      pfreeBytes = (unsigned long int)HPB.ioVFrBlk * 
 HPB.ioVAlBlkSiz / 1024;
    else
        pfreeBytes = 0L;    
    return(pfreeBytes);            

}

#pragma segment PrintImage
pascal void TReportPrinter::UserAbort(void) 
{
 // so we’ll fall out of the print loop
 fUserAborted = true; 
 // window’s been freed so forget about it
 fMyStatusWindow = nil;   
}

//•••••• TReportStatusWindow ••••••

#pragma segment PrintImage
pascal void TReportStatusWindow::IReportStatusWindow(
 TReportPrinter *aPrinter)
{
 fMyPrinter = aPrinter;
}

#pragma segment PrintImage
pascal void TReportStatusWindow::DoCommandKeyEvent(
 TToolboxEvent* event)
{
 if(event->fCharacter == ‘.’) {
 // tell the ReportPrinter to bail out
 fMyPrinter->UserAbort(); 
 this->Close();  
 }
 else
 inherited::DoCommandKeyEvent(event);
}

#pragma segment PrintImage
pascal void TReportStatusWindow::SetMessage(
 CStr255 theMessage)
{
 FailInfo fi;
 if(fi.Try()) {
 TStaticText *theText = (TStaticText *) 
 FindSubView(kDocumentNameID);
 theText->SetText(theMessage, true);
 fi.Success();
 }
 else {
 fi.ReSignal();
 }
}

 

Community Search:
MacTech Search:

Software Updates via MacUpdate

FotoMagico 5.6.12 - Powerful slideshow c...
FotoMagico lets you create professional slideshows from your photos and music with just a few, simple mouse clicks. It sports a very clean and intuitive yet powerful user interface. High image... Read more
OmniGraffle Pro 7.12.1 - Create diagrams...
OmniGraffle Pro helps you draw beautiful diagrams, family trees, flow charts, org charts, layouts, and (mathematically speaking) any other directed or non-directed graphs. We've had people use... Read more
beaTunes 5.2.1 - Organize your music col...
beaTunes is a full-featured music player and organizational tool for music collections. How well organized is your music library? Are your artists always spelled the same way? Any R.E.M. vs REM?... Read more
HandBrake 1.3.0 - Versatile video encode...
HandBrake is a tool for converting video from nearly any format to a selection of modern, widely supported codecs. Features Supported Sources VIDEO_TS folder, DVD image or real DVD (unencrypted... Read more
Macs Fan Control 1.5.1.6 - Monitor and c...
Macs Fan Control allows you to monitor and control almost any aspect of your computer's fans, with support for controlling fan speed, temperature sensors pane, menu-bar icon, and autostart with... Read more
TunnelBear 3.9.3 - Subscription-based pr...
TunnelBear is a subscription-based virtual private network (VPN) service and companion app, enabling you to browse the internet privately and securely. Features Browse privately - Secure your data... Read more
calibre 4.3.0 - Complete e-book library...
Calibre is a complete e-book library manager. Organize your collection, convert your books to multiple formats, and sync with all of your devices. Let Calibre be your multi-tasking digital librarian... Read more
Lyn 1.13 - Lightweight image browser and...
Lyn is a fast, lightweight image browser and viewer designed for photographers, graphic artists, and Web designers. Featuring an extremely versatile and aesthetically pleasing interface, it delivers... Read more
Visual Studio Code 1.40.0 - Cross-platfo...
Visual Studio Code provides developers with a new choice of developer tool that combines the simplicity and streamlined experience of a code editor with the best of what developers need for their... Read more
OmniGraffle 7.12.1 - Create diagrams, fl...
OmniGraffle helps you draw beautiful diagrams, family trees, flow charts, org charts, layouts, and (mathematically speaking) any other directed or non-directed graphs. We've had people use Graffle to... Read more

Latest Forum Discussions

See All

The House of Da Vinci 2 gets a new gamep...
The House of Da Vinci launched all the way back in 2017. Now, developer Blue Brain Games is gearing up to deliver a second dose of The Room-inspired puzzling. Some fresh details have now emerged, alongside the game's first official trailer. [Read... | Read more »
Shoot 'em up action awaits in Battl...
BattleBrew Productions has just introduced another entry into its award winning, barrelpunk inspired, BattleSky Brigade series. Whilst its previous title BattleSky Brigade TapTap provided fans with idle town building gameplay, this time the... | Read more »
Arcade classic R-Type Dimensions EX blas...
If you're a long time fan of shmups and have been looking for something to play lately, Tozai Games may have just released an ideal game for you on iOS. R-Type Dimensions EX brings the first R-Type and its sequel to iOS devices. [Read more] | Read more »
Intense VR first-person shooter Colonicl...
Our latest VR obsession is Colonicle, an intense VR FPS, recently released on Oculus and Google Play, courtesy of From Fake Eyes and Goboogie Games. It's a pulse-pounding multiplayer shooter which should appeal to genre fanatics and newcomers alike... | Read more »
PUBG Mobile's incoming update bring...
PUGB Mobile's newest Royale Pass season they're calling Fury of the Wasteland arrives tomorrow and with it comes a fair chunk of new content to the game. We'll be seeing a new map, weapon and even a companion system. [Read more] | Read more »
PSA: Download Bastion for free, but wait...
There hasn’t been much news from Supergiant Games on mobile lately regarding new games, but there’s something going on with their first game. Bastion released on the App Store in 2012, and back then it was published by Warner Bros. This Warner... | Read more »
Apple Arcade: Ranked - 51+ [Updated 11.5...
This is Part 2 of our Apple Arcade Ranking list. To see part 1, go here. 51. Patterned [Read more] | Read more »
NABOKI is a blissful puzzler from acclai...
Acclaimed developer Rainbow Train's latest game, NABOKI, is set to launch for iOS, Android, and Steam on November 13th. It's a blissful puzzler all about taking levels apart in interesting, inventive ways. [Read more] | Read more »
A Case of Distrust is a narrative-driven...
A Case of Distrust a narrative-focused mystery game that's set in the roaring 20s. In it, you play as a detective with one of the most private eye sounding names ever – Phyllis Cadence Malone. You'll follow her journey in San Francisco as she... | Read more »
Brown Dust’s October update offers playe...
October is turning out to be a productive month for the Neowiz team, and a fantastic month to be a Brown Dust player. First, there was a crossover event with the popular manga That Time I Got Reincarnated as a Slime. Then, there was the addition of... | Read more »

Price Scanner via MacPrices.net

Score a 37% discount on Apple Smart Keyboards...
Amazon has Apple Smart Keyboards for current-generation 10″ iPad Airs and previous-generation 10″ iPad Pros on sale today for $99.99 shipped. That’s a 37% discount over Apple’s regular MSRP of $159... Read more
Apple has refurbished 2019 13″ 1.4GHz MacBook...
Apple has a full line of Certified Refurbished 2019 13″ 1.4GHz 4-Core Touch Bar MacBook Pros available starting at $1099 and up to $230 off MSRP. Apple’s one-year warranty is included, shipping is... Read more
2019 13″ 1.4GHz 4-Core MacBook Pros on sale f...
Amazon has new 2019 13″ 1.4GHz 4-Core Touch Bar MacBook Pros on sale for $150-$200 off Apple’s MSRP. These are the same MacBook Pros sold by Apple in its retail and online stores: – 2019 13″ 1.4GHz/... Read more
11″ 64GB Gray WiFi iPad Pro on sale for $674,...
Amazon has the 11″ 64GB Gray WiFi iPad Pro on sale today for $674 shipped. Their price is $125 off MSRP for this iPad, and it’s the lowest price available for the 64GB model from any Apple reseller. Read more
2019 15″ MacBook Pros available for up to $42...
Apple has a full line of 2019 15″ 6-Core and 8-Core Touch Bar MacBook Pros, Certified Refurbished, available for up to $420 off the cost of new models. Each model features a new outer case, shipping... Read more
2019 15″ MacBook Pros on sale this week for $...
Apple resellers B&H Photo and Amazon are offering the new 2019 15″ MacBook Pros for up to $300 off Apple’s MSRP including free shipping. These are the same MacBook Pros sold by Apple in its... Read more
Sunday Sale: AirPods with Wireless Charging C...
B&H Photo has Apple AirPods with Wireless Charging Case on sale for $159.99 through 11:59pm ET on November 11th. Their price is $40 off Apple’s MSRP, and it’s the lowest price available for these... Read more
Details of Sams Club November 9th one day App...
Through midnight Saturday night (November 9th), Sams Club online has several Apple products on sale as part of their One Day sales event. Choose free shipping or free local store pickup (if available... Read more
Sprint is offering the 64GB Apple iPhone 11 f...
Sprint has the new 64GB iPhone 11 available for $15 per month for new lines. That’s about 50% off their standard monthly lease of $29.17. Over is valid until November 24, 2019. The fine print: “Lease... Read more
New Sprint November iPhone deal: Lease one iP...
Switch to Sprint and purchase an Apple iPhone 11, 11 Pro, or 11 Pro Max, and get a second 64GB iPhone 11 for free. Requires 2 new lines or 1 upgrade-eligible line and 1 new line. Offer is valid from... Read more

Jobs Board

*Apple* Mobility Pro - Best Buy (United Stat...
**746087BR** **Job Title:** Apple Mobility Pro **Job Category:** Store Associates **Store NUmber or Department:** 000319-Harlem & Irving-Store **Job Description:** Read more
Best Buy *Apple* Computing Master - Best Bu...
**743392BR** **Job Title:** Best Buy Apple Computing Master **Job Category:** Store Associates **Store NUmber or Department:** 001171-Southglenn-Store **Job Read more
Best Buy *Apple* Computing Master - Best Bu...
**746015BR** **Job Title:** Best Buy Apple Computing Master **Job Category:** Sales **Store NUmber or Department:** 000372-Federal Way-Store **Job Description:** Read more
*Apple* Mobility Pro - Best Buy (United Stat...
**744658BR** **Job Title:** Apple Mobility Pro **Job Category:** Store Associates **Store NUmber or Department:** 000586-South Hills-Store **Job Description:** At Read more
Best Buy *Apple* Computing Master - Best Bu...
**741552BR** **Job Title:** Best Buy Apple Computing Master **Job Category:** Sales **Store NUmber or Department:** 000277-Metcalf-Store **Job Description:** **What Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.