Retired Document
Important: This sample code may not represent best practices for current development. The project may use deprecated symbols and illustrate technologies and techniques that are no longer recommended.
source/OldApp.c
/* |
copyright © 1992-1994 Apple Computer Inc. All rights reserved. |
OldApp.c |
This file implements old application message overrides for the specific driver. |
Included in this file is the old PrintRecord emulation. Note that the ImageWriter |
PrintRecord is a wonder of misdirection and special cases. You'll have fun |
figuring out the code - so unless you really want to exactly emulate the ImageWriter |
pages, you shouldn't spend too much time looking at this code. |
Modification history |
7/23/92 TED New file today |
12/20/93 dmh Sync'd with the shipping 1.0b3 GX driver. |
8/26/94 dmh Sync'd with the shipping 1.0.1 GX driver. |
*/ |
// Include the standard Mac header files |
#include <Errors.h> |
#include <ToolUtils.h> |
#include <StdIO.h> |
#include <StdLib.h> |
#include <String.h> |
#include <Strings.h> |
#include <Resources.h> |
#include <ToolUtils.h> |
#include <OSUtils.h> |
#include <Files.h> |
#include <Types.h> |
#include <Packages.h> |
#include <Memory.h> |
#include <Serial.h> |
#include <Devices.h> |
#include <Fonts.h> |
#include <Printing.h> |
#include <Script.h> |
#include <Events.h> |
#include <Dialogs.h> |
#include <FixMath.h> |
#include <Lists.h> |
#include <AppleTalk.h> |
#include <Menus.h> |
#include <Events.h> |
#include <Balloons.h> |
#include <Folders.h> |
#include <SCSI.h> |
// Include the new QuickDraw GX graphics header files |
#include <GXGraphics.h> |
#include <GXMath.h> |
#include <QDLibrary.h> |
#include <FontLibrary.h> |
#include <GXLayout.h> |
#include <GraphicsLibraries.h> |
// Include the required Printing Manager header files |
#include <GXPrinting.h> |
#include <GXPrinterDrivers.h> |
#include <CollectionLibrary.h> |
#include <JobFormatModeLibrary.h> |
#include <PaperTypeLibrary.h> |
#include <PicturesAndPICTLibrary.h> |
#include <Collections.h> |
#include <GXMessages.h> |
#include "CommonDefines.h" // things common to .r and .h files |
#include "DriverProtos.h" |
#if defined(__MWERKS__) |
asm void __Startup__(void); |
asm void __Startup__(void) |
{ |
dc.l 0 // Reserved for owner count. |
jmp SD_ConvertPrintRecordTo |
jmp SD_ConvertPrintRecordFrom |
jmp SD_PrintRecordToJob |
jmp SD_PrValidate |
jmp SD_PrJobInit |
RTS // this is needed so __Startup__ symbol works |
} |
#endif |
/* ---------------------------------------------------------------------------- */ |
/* INTERNAL TYPEDEFS AND STRUCTURES */ |
/* ---------------------------------------------------------------------------- */ |
// ImageWriter wDev values |
#define kBest 0x01 |
#define kPortrait 0x02 |
#define kTallAdjusted 0x04 |
#define k50Percent 0x08 |
#define kNoGaps 0x10 |
#define kSetResCalled 0x20 |
// some ImageWriter constants |
#define kGapSize 60 // gap at top of page in 120ths of an inch |
#define kSmallPlaten 16 // platen width in half inches for small IW |
#define kBigPlaten 27 // platen width in half inches for the 15" IW |
/* ---------------------------------------------------------------------------- */ |
/* FORWARD DECLARES */ |
/* ---------------------------------------------------------------------------- */ |
OSErr SD_ConvertPrintRecordTo(THPrint hoPrint); |
OSErr SD_ConvertPrintRecordFrom(gxUniversalPrintRecordHdl huPrint); |
/* ---------------------------------------------------------------------------- */ |
/* INTERNAL ROUTINES */ |
/* ---------------------------------------------------------------------------- */ |
OSErr UpdatePrintRecord(THPrint hPrint) |
{ |
OSErr anErr; |
gxUniversalPrintRecordHdl huPrint = (gxUniversalPrintRecordHdl)hPrint; |
gxUniversalPrintRecordPtr puPrint; |
short devVRes, devHRes, appVRes, appHRes; |
short cPlaten; |
// convert to universal format |
anErr = SD_ConvertPrintRecordTo(hPrint); |
if (anErr == noErr) |
{ |
// determine application & device resolutions, based upon quality mode, tall adjusted |
// setting, and if the app called SetRsl: |
// draft - 80(h)*72(v) |
// faster - 80(h)*72(v) |
// best - 160(h)*144(v) |
// |
// draft (tall adjusted) - 72*72 |
// faster (tall adjusted) - 72*72 |
// best (tall adjusted) - 144*144 |
puPrint = *huPrint; |
if (puPrint->options & gxPreciseBitmap) |
switch(puPrint->qualityMode) |
{ |
case gxDraftQuality: |
case gxFasterQuality: |
devVRes = devHRes = 72; |
appVRes = appHRes = 72; |
break; |
case gxBestQuality: |
devVRes = devHRes = 144; |
appVRes = appHRes = 72; |
break; |
} |
else |
switch(puPrint->qualityMode) |
{ |
case gxDraftQuality: |
case gxFasterQuality: |
appVRes = devVRes = 72; |
appHRes = devHRes = 80; |
break; |
case gxBestQuality: |
devVRes = 144; |
devHRes = 160; |
appVRes = 72; |
appHRes = 80; |
break; |
} |
// SetRsl was called? Use the resolution specified by the application |
if (puPrint->appVRes != 72) |
{ |
appVRes = devVRes = puPrint->appVRes; |
appHRes = devHRes = puPrint->appHRes; |
} |
// finally, store the app & device resolutions |
puPrint->devVRes = devVRes; |
puPrint->devHRes = devHRes; |
puPrint->appVRes = appVRes; |
puPrint->appHRes = appHRes; |
// here we do page size calculations |
// Please note that this code is confusing - it's purpose is to emulate |
// the existing ImageWriter driver's page size. Most drivers would not |
// do this - the existing in the system probably is good enough. |
{ |
long pageGap; // gap at top of page |
long dvPaper, dhPaper; // paper size at device res |
long dvPage, dhPage; // page size at device res |
long scanLines, scanBits; // # of scan lines or bits on page |
long maxH; // maximum width |
long hOff, vOff; // margins (horiz & vert) to get paper rect from page rect |
// gap at the top of the page in pixels |
pageGap = (kGapSize * appVRes) / 120; |
if (puPrint->options & gxBiggerPages) |
pageGap = 0; |
// figure out paper size in application space pixels |
dvPaper = (puPrint->pageV * appVRes) / 120; |
dhPaper = (puPrint->pageH * appHRes) / 120; |
// vertically, align to the head height of 8 pixels |
scanLines = ((dvPaper - pageGap) >> 3) << 3; |
// horizontally, allow the biggest width we can handle |
cPlaten = kSmallPlaten; |
if (puPrint->pageH > (9*120) ) |
cPlaten = kBigPlaten; |
maxH = (cPlaten * appHRes) >> 1; |
if (maxH > dhPaper) |
maxH = dhPaper; |
scanBits = (maxH >> 4) << 4; |
if (puPrint->orientation == gxPortraitOrientation) |
{ |
// portrait |
dhPage = scanBits; |
dvPage = scanLines; |
hOff = (dhPage - dhPaper) >> 1; |
vOff = -pageGap; |
} |
else |
{ |
// landscape |
dhPage = scanLines; |
dvPage = scanBits; |
// reverse the paper definition as well |
{ |
long iTemp = dhPaper; |
dhPaper = dvPaper; |
dvPaper = iTemp; |
} |
hOff = -pageGap; |
vOff = (dvPage - dvPaper) >> 1; |
} |
// 50% reduction? scale everything by 2X |
if (puPrint->options & gxUserFlag0) |
{ |
dhPage <<= 1; |
dvPage <<= 1; |
dhPaper <<= 1; |
dvPaper <<= 1; |
hOff <<= 1; |
vOff <<= 1; |
} |
// set the page and paper in app space |
puPrint->appPage.left = puPrint->appPage.top = 0; |
puPrint->appPage.right = dhPage; |
puPrint->appPage.bottom = dvPage; |
puPrint->appPaper.left = hOff; |
puPrint->appPaper.top = vOff; |
puPrint->appPaper.right = dhPaper + hOff; |
puPrint->appPaper.bottom = dvPaper + vOff; |
// from page, scale up to device space (in case some weenie decides to look at that) |
puPrint->devPage.left = puPrint->devPage.top = 0; |
puPrint->devPage.right = dhPage * devHRes / appHRes; |
puPrint->devPage.bottom = dvPage * devVRes / appVRes; |
} |
// convert back to non-universal format |
anErr = SD_ConvertPrintRecordFrom((gxUniversalPrintRecordHdl) hPrint); |
} |
return(anErr); |
} // UpdatePrintRecord |
//<FF> |
/* ---------------------------------------------------------------------------- */ |
/* MESSAGE OVERRIDES */ |
/* ---------------------------------------------------------------------------- */ |
OSErr SD_ConvertPrintRecordTo(THPrint hoPrint) |
/* |
This call takes a print record in old style (driver specific) format, and |
converts it to the format of "gxUniversalPrintRecordHdl" |
*/ |
{ |
TPPrint poPrint; // pointer to old style print record |
gxUniversalPrintRecordHdl huPrint = (gxUniversalPrintRecordHdl)hoPrint; // handle to universal print record |
gxUniversalPrintRecordPtr puPrint; // pointer to universal print record |
short qualityMode; // cached quality mode |
short wDev; // cached wDev |
// cache pointers for size and speed |
puPrint = *huPrint; |
poPrint = *hoPrint; |
wDev = poPrint->prStl.wDev; |
// determine quality mode |
if (poPrint->prJob.bJDocLoop == 0) |
qualityMode = gxDraftQuality; |
else |
{ |
if (wDev & kBest) |
qualityMode = gxBestQuality; |
else |
qualityMode = gxFasterQuality; |
} |
// universal feed is the inverse of our feed |
puPrint->feed = 1-(poPrint->prStl.feed); |
// wDev 0x02 means portrait, else landscape |
if (wDev & kPortrait) |
puPrint->orientation = gxPortraitOrientation; |
else |
{ |
puPrint->orientation = gxLandscapeOrientation; |
// landscape disabled draft, forces tall adjusted |
if (qualityMode == gxDraftQuality) |
qualityMode = gxFasterQuality; |
wDev |= kTallAdjusted; |
} |
// copies are in iCopies field (wow.) |
puPrint->actualCopies = poPrint->prJob.iCopies; |
// store our flags |
puPrint->options = 0; |
// tall adjusted |
if (wDev & kTallAdjusted) |
puPrint->options |= gxPreciseBitmap; |
// 50% reduction |
if (wDev & k50Percent) |
{ |
puPrint->options |= gxUserFlag0; |
puPrint->reduction = 50; |
// for 50% reduction, we always return faster to the application |
qualityMode = gxFasterQuality; |
} |
else |
puPrint->reduction = 100; |
// no gaps |
if (wDev & kNoGaps) |
puPrint->options |= gxBiggerPages; |
// finally, store quality mode |
puPrint->qualityMode = qualityMode; |
// and we can't have any errors - because this code is too godlike. |
return(noErr); |
} // SD_ConvertPrintRecordTo |
//<FF> |
/* ---------------------------------------------------------------------------- */ |
OSErr SD_ConvertPrintRecordFrom(gxUniversalPrintRecordHdl huPrint) |
/* |
This call takes a print record in universal format and converts it |
to old style (driver specific) format. |
Note: for the ImageWriter, I'm filling in way more things than theoretically |
I need to. However, since the ImageWriter is one of the oldest print drivers, |
there is much more of a chance that someone assumes something about one or |
more of the fields. |
*/ |
{ |
gxUniversalPrintRecordPtr puPrint; // pointer to universal print record |
THPrint hoPrint = (THPrint)huPrint; // handle to old style print record |
TPPrint poPrint; // pointer to old style print record |
short options; // cached universal options |
short qualityMode; // cached universal quality mode |
short actualCopies; // cached universal copies |
// cache pointers for size and speed |
puPrint = *huPrint; |
poPrint = *hoPrint; |
// save away fields within the universal record that we'll be stomping over |
// as we convert |
options = puPrint->options; |
qualityMode = puPrint->qualityMode; |
actualCopies = puPrint->actualCopies; |
poPrint->iPrVersion = 4; // used to be 3, but this is |
// a new driver. We support versions |
// 3 and 4 |
poPrint->prInfo.iDev = 0; // always zero for the ImageWriter |
// skip remaining fields in prInfo because they are unchanged |
// determine the wDev |
{ |
short wDev; |
// this is the wDev value for the ImageWriter |
wDev = 0x0100; |
if (puPrint->orientation == gxPortraitOrientation) |
wDev |= kPortrait; |
else |
{ |
// for landscape, disable draft and force tall adjusted |
if (qualityMode == gxDraftQuality) |
qualityMode = gxFasterQuality; |
options |= gxPreciseBitmap; |
} |
// user options |
if (options & gxPreciseBitmap) |
wDev |= kTallAdjusted; |
if (options & gxUserFlag0) |
{ |
wDev |= k50Percent; |
qualityMode = gxFasterQuality; |
} |
if (options & gxBiggerPages) |
wDev |= kNoGaps; |
// if the application's resolution isn't 72 - then clearly SetRsl must have been called |
// to change it. |
if (poPrint->prInfo.iVRes != 72) |
{ |
wDev |= kSetResCalled; |
qualityMode = gxBestQuality; |
} |
if (qualityMode == gxBestQuality) |
wDev |= kBest; |
// and finally, save away that short value we worked so hard to determine |
poPrint->prStl.wDev = wDev; |
} |
// other fields in prStl remain the same |
poPrint->prStl.bPort = 0; |
poPrint->prStl.feed = 1 - (puPrint->feed); |
poPrint->prInfoPT.iDev = (qualityMode == gxBestQuality) ? -768 : 0; |
// other fields in prInfoPT remain the same |
{ |
Rect rPage = poPrint->prInfoPT.rPage; |
// calculate some fields we don't use - in case someone really wants to look at |
// them for some reason |
poPrint->prXInfo.iRowBytes = rPage.right >> 3; |
poPrint->prXInfo.iBandV = 32; |
poPrint->prXInfo.iBandH = poPrint->prXInfo.iRowBytes << 3; |
poPrint->prXInfo.iDevBytes = poPrint->prXInfo.iRowBytes * |
poPrint->prXInfo.iBandV + |
poPrint->prXInfo.iBandH; |
poPrint->prXInfo.iBands = (rPage.bottom+(poPrint->prXInfo.iBandV-1)) / poPrint->prXInfo.iBandV; |
poPrint->prXInfo.bPatScale = (qualityMode == gxBestQuality) ? -2 : 0; |
poPrint->prXInfo.bUlThick = 1; |
poPrint->prXInfo.bUlOffset = 1; |
poPrint->prXInfo.bUlShadow = 1; |
poPrint->prXInfo.scan = (poPrint->prStl.wDev & kPortrait) ? 0 : 2; |
poPrint->prXInfo.bXInfoX = 0; |
} |
// other fields in prJob remain the same |
poPrint->prJob.iCopies = actualCopies; |
poPrint->prJob.bJDocLoop = (qualityMode == gxDraftQuality) ? 0 : 1; |
// this routine is so studly, there can be no errors |
return(noErr); |
} // SD_ConvertPrintRecordFrom |
//<FF> |
/* ---------------------------------------------------------------------------- */ |
OSErr SD_PrintRecordToJob(THPrint hPrint, gxJob theJob) |
/* |
We convert the "tall adjusted" setting into the correct rendering option for |
the job collection. |
*/ |
{ |
OSErr anErr; |
Handle jobQualitySettingsHdl; |
anErr = Forward_GXPrintRecordToJob(hPrint, theJob); |
if (anErr == noErr) |
{ |
long imagewriterOptions = kSuperRes; |
if ((**hPrint).prStl.wDev & kSetResCalled) |
{ |
Collection jobCollection = GXGetJobCollection(GXGetJob()); |
gxQualityInfo *qualitySettings; |
// get old info and replace it with final quality |
jobQualitySettingsHdl = NewHandle(0); |
anErr = MemError(); |
nrequire(anErr, FailedNewHandle); |
anErr = GetCollectionItemHdl ( jobCollection, |
gxQualityTag, |
gxPrintingTagID, |
jobQualitySettingsHdl ); |
if (anErr == collectionItemNotFoundErr) |
{ |
Str255 bestString, roughString; |
Size count1, count2; |
Ptr p; |
short curResFile = CurResFile(); |
UseResFile(GXGetMessageHandlerResFile()); |
GetIndString( bestString, kOldQualityID, kBestString); |
GetIndString( roughString, kOldQualityID, kRoughString); |
UseResFile(curResFile); |
SetHandleSize(jobQualitySettingsHdl,(sizeof(gxQualityInfo) + bestString[0] + roughString[0] + 2 )); |
anErr = MemError(); |
nrequire( anErr, FailedSetHandleSize ); |
qualitySettings = *((gxQualityInfo **) jobQualitySettingsHdl); |
qualitySettings->disableQuality = false; |
qualitySettings->defaultQuality = 1; |
qualitySettings->currentQuality = 1; |
qualitySettings->qualityCount = 2; |
count1 = bestString[0]+1; |
p = qualitySettings->qualityNames; |
BlockMove( bestString, p, count1 ); |
count2 = roughString[0]+1; |
p += count1; |
BlockMove( roughString, p, count2 ); |
} |
else |
qualitySettings = *((gxQualityInfo **) jobQualitySettingsHdl); |
(qualitySettings->currentQuality = qualitySettings->qualityCount-1); |
anErr = AddCollectionItemHdl ( jobCollection, |
gxQualityTag, |
gxPrintingTagID, |
jobQualitySettingsHdl ); |
if (anErr == noErr) |
(void) SetCollectionItemInfo(jobCollection, gxQualityTag, gxPrintingTagID, 0x0000FFFF, gxVolatileOutputDriverCategory); |
DisposHandle(jobQualitySettingsHdl); |
} |
if ((**hPrint).prStl.wDev & kTallAdjusted) |
imagewriterOptions = 0; |
if (anErr == noErr) |
anErr = AddCollectionItem(GXGetJobCollection(theJob), |
DriverCreator, |
0, |
sizeof(imagewriterOptions), |
&imagewriterOptions); |
} |
FailedNewHandle: |
return(anErr); |
FailedSetHandleSize: |
DisposHandle(jobQualitySettingsHdl); |
return(anErr); |
} // SD_PrintRecordToJob |
//<FF> |
/* ---------------------------------------------------------------------------- */ |
OSErr SD_PrValidate( THPrint hPrint, // old style print record |
Boolean *wasChanged) // was the print record changed? |
/* |
This call validates the current print record. It's fairly simplistic (as were |
all of the old drivers) - the wDev or versions don't match the current, we call |
PrintDefault. Otherwise, we call UpdatePrintRecord - to allow the driver to sanity |
check any internal fields. |
*/ |
{ |
unsigned short wDev; // note: if this were signed, the shift below would fail |
Boolean recordIsInvalid = true; |
OSErr anErr = noErr; |
// check the wDev. The upper byte must be equal to our idea of the wDev |
wDev = (**hPrint).prStl.wDev; |
wDev >>= 8; // get just the device ID |
// If the device id is equal, then check the version number of the print record. |
// Only if that is also equal to the current version, will we return false (valid). |
if ( (wDev == 1) |
&& |
( |
( ((**hPrint).iPrVersion) == 3 ) || |
( ((**hPrint).iPrVersion) == 4 ) |
) |
) |
recordIsInvalid = false; |
// If the the print record is not valid, then return the default print record. |
// Otherwise, update the print record, based on the application's calls |
// to PrGeneral. |
if (recordIsInvalid) |
PrintDefault(hPrint); |
else |
anErr = UpdatePrintRecord(hPrint); |
*wasChanged = recordIsInvalid; |
return (anErr); |
} // SD_PrValidate |
//<FF> |
/* ---------------------------------------------------------------------------- */ |
OSErr SD_PrJobInit(THPrint hPrint, TPPrDlg * pDlg) |
/* |
This routine is called to initialize the job dialog. We take the default |
behavior - and then disable some of the items based on settings the user |
has made: |
- 50% disables all items |
- apps that call SetRsl disable all items |
- landscape disables draft mode |
*/ |
{ |
OSErr anErr; |
anErr = Forward_GXPrJobInit(hPrint, pDlg); |
if (anErr == noErr) |
{ |
Boolean disableDraft = false; |
Boolean disableAll = false; |
short wDev = (**hPrint).prStl.wDev; |
short idx; |
Rect box; |
Handle item; |
short type; |
if (wDev & k50Percent) |
disableAll = true; |
if (wDev & kSetResCalled) |
disableAll = true; |
if (!(wDev & kPortrait)) |
disableDraft = true; |
// disable any controls we need to |
for (idx = 6; idx <= 8; ++idx) |
{ |
GetDItem((DialogPtr) *pDlg, idx, &type, &item, &box); |
if ( (disableAll) || ((disableDraft) && (idx == 8) ) ) |
HiliteControl((ControlHandle) item, 255); |
} |
} |
return(anErr); |
} // SD_PrJobInit |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-01-14