TweetFollow Us on Twitter

All About Printing
Volume Number:1
Issue Number:9
Column Tag:Pascal Procedures

“All About Printing”

By Alan Wootton, President, Top-Notch Productions, MacTutor Contributing Editor

This month's topic is printing. As an example I present a program that will print a message in large, 'banner' format. Perfect for parties!

To those of us who are familiar with the older generation of computers, printing is a matter of sending data through ports and using printer control codes. For the Mac we take these details for granted and will concentrate on using pre-packaged drivers and on the details of GrafPorts.

Background

Printing on the Mac is done through the Printing Manager, RAM software that is considered part of the low-level operating system software. This code is stored in the system file and loaded into RAM. The Printing Manager interfaces between your program and the actual printer driver that controls the printer. The Imagewriter and LaserPrinter files are printer drivers called by the Printing Manager. The "Choose Printer" desk accessory switches between the two drivers so the Printing Manager has the correct driver installed and ready to go. To be more specific, the Imagewriter and LaserPrinter files are printer resource files, which contain device driver code within them to drive the respective printer. The "Choose Printer" DA copies the selected printer driver and it's data structures from the printer resource file into the system file, and that's the driver that the Print Manger then uses. The idea is that a Mac application can be written using printing manager calls and be printer independent, since the printing manager would then interface to the appropriate device driver, eliminating the need to re-code an application for a different printer. This ideal comes close to being achieved on the Mac, probably more than any other computer system, but is still far from perfect.

The intent of the Mac designers was that printing would be transparent to quickdraw graphics "printed" on the screen. This was accomplished by using a special quickdraw grafport for printing. Normal quickdraw routines are used to draw into this port. The Printing Manager converts these quickdraw calls in your grafport to printer calls to drive the printer instead of the screen. In this way, printing is supposed to be transparent to a normal screen drawing operation. It also explains the complexity of printing, since it involves all the quickdraw screen graphics technology.

Draft versus Standard Quality

The Printing Manager is responsible for the dialog boxes that appear prior to printing and for allowing draft or standard quality printing. These two modes are fundamentally different. In draft mode, the ascii representation of the quickdraw calls are sent to the printer, which prints the text of the document using the character generator within the printer. Hence no graphics are supported except character graphics or modes directly supported by the printer and driven by the user's program. The printer responds to it's own command codes rather than any of the "Mac" like graphics.

Spool File versus Printing the Spool File

Standard and high quality modes are completely different. In these modes, the printer is controlled bit by bit and the entire document is converted into a giant bit mapped graphics dump. A temporary quickdraw picture is first composed on disk called the spool file. This spool file is then read into memory, converted into an array of dots by bands, and sent to the printer. The bands are necessary because of the huge amount of memory required by bit-mapping an 81/2 by 11 inch page. For the imagewriter, this amounts to 256K of memory. For the LaserWriter, over a megabyte! The task of first creating a quickdraw picture for the spool file, and then imaging (converting to a bit-map) and printing the spool file band by band, are handled seperately by the printing manager. In fact, it is supposed to be possible to create several spool files for printing later, but no one seems to be using that ability. Inside Mac appears indecisive about printing, saying that printing spool files is done by the Printer utility, the code of which has apparently been integrated into the Finder. But Printer does exist as a seperate utility that will read a spool file, image it and print it. Since hardly any applications leave the spool file lying around, there hasen't been much opportunity to use the Printer utility.

Print Manager Calls: Lisa Pascal to Mac Pascal

In the printing chapter of Inside Mac a lengthy list of data types is presented along with 14 Pascal procedures and functions. This is the printing interface, but it is not made clear exactly where these procedures are found. The idea is that you are supposed to simply include the declarations and calls in your program and then link with a printing module. What is misleading about this is that the link is not with the procedures you think you are using but merely a piece of "glue". The actual code used to drive the printer is in the file 'Imagewriter' (usually in the system folder). Naturally, the code is in resources.

Imagewriter

To get a handle (pun intended) on printing, I examined the link module provided by Owen Densmore. I then duplicated Owen's algorithms in Pascal. You can find my versions of all 14 procedures in the following program.

The first task is to open a resource file. I said a bit on resources last month and there is never enough I can say about them. You should take a look in 'Imagewriter' and see what is there. The resources of interest here are of TYPE PDEF. These resources are actual printer-specific code. The code we need is in PDEF#0, PDEF#1, PDEF#4, and PDEF#5. In 'Imagewriter' is also a driver DRVR#-8192 named, '.print', but the one actually used is installed in the file, 'system'. The other stuff is for support of the dialog boxes the print manager presents. Rather than simply OpenResFile('Imagewriter');, we must take into account the possibility that there is more than one printer. To this end there is a resource STR #-8192 which contains the name of the print resource file. Therefore the print procedure PrOpen is ResID := OpenResFile( GetString(-8192) ); along with PBOpen of '.Print'. PrClose is simply CloseResFile(ResID). The other print procedures are in the PDEF resources and begin at various offsets into those resources.

The function GetAddress is used in the program to load one of the PDEF's (GetResource) and then to lock it in place (Hlock). It is then dereferenced and the offset is added. Once we have an absolute address to use we need a way to pass control to it. To do this I created the array jsr[0..3] of integer which contains code to JSR to the address on the top of the stack. Once again I take advantage of the fact that InlineP leaves register A0 pointing 2 bytes behind of the place we must return to. If you know no 68000 assembly you can ignore this.

The final detail to emulating the print interface code is that some of the routines release the PDEF handle and others leave it locked in place. This is the purpose of ReleaseAddress. Further, note that some of the routines use different PDEF's (0,1,2 or 3) depending on the setting of bjDocLoop. This is the purpose of MethodAdd. I find this a rather obscure feature and it will not be used here; nonetheless, the interface presented is complete, I think.

GrafPorts for Printing

It is necessary to use the type declarations to print but it is not necessary to closely study their form or function. I suggest studying my print record declarations in the program below along side "Printing Resources" in the new telephone version of Inside macintosh, where the print data structures are explained. A print record is created and filled in by the Printing Manager and the print dialog boxes. The printing port is set by a variant record type so that your program can write into the port as if it were a regular grafport, while the Printing Manager can modify the grafport for the printer.

The central issue is one of drawing in a GrafPort. Essentially, printing is no different than updating the contents of a window except that the size of the window is huge. To simply print a picture use a sequence like PrOpen, PrintDefault, PrOpenDoc, PrOpenPage, draw your picture, PrClosePage, PrCloseDoc, PrPicFile, and PrClose. To print more pages repeat PrOpenPage, draw, PrClosePage. Note the perfect symmetry with the exception of PrintDefault and PrPicFile. PrintDefault will fill in all those nasty hPrint fields for you and PrPicFile actually drives the printer. You may also modify your hPrint with PrStlDialog and PrJobDialog. These two present very familiar dialog boxes.

In the following program the procedure DrawPic draws a large picture in whatever port is current. In the main body of the program DrawPic is called several times to demonstrate the use of SetOrgin to show different views of the big picture. Of course, the parts of the picture that don't fit are chopped off by quickdraw and the same will happen when we print. I have found some strange complications. When printing, the VisRgn of the print port is not used, rather the clipRgn is used to delineate the usable area. In contrast, the drawing example opens up the ClipRgn and the VisRgn presents the limits. To investigate put:

with MyPort^.VisRgn^^.rgnBBox do writeln(top,left,bottom,right);  

in various places.

If you are doing a picture that is larger than one page don't assume the size of the page. You won't have to mess around in the grafport because you can use the rectangle hPrint^^.prInfoPt.Rpage to obtain the necessary offsets. Rpage.top and Rpage.left are zero so use right and bottom. I think this is the only one of the many hPrint fields that is commonly useful.

To make a banner, as promised, you will need the newer version of Imagewriter (sometimes called Imagewriter 15) or else there will be breaks between the pages. For banner format choose 'wide' and 'no breaks between pages' on the style dialog. You can change DrawPic to make any picture you please.

If there is any, and I mean any, subject that you think needs to be covered, write to me care of MacTutor and I will give it a try. I figure that if we can print with MacPascal then MacPascal can do just about anything.

program Banner_Print;{ by Alan Wootton 5/85 }
{ Prints a test pattern using the Printing Manager }

 uses
  Quickdraw2;
 type
  ptr = ^integer;
  handle = ^ptr;
  ProcPtr = ^longint;
  OStype = longint;

  strptr = ^str255;
  strHan = ^strptr;

{~~~~~~~~~ Print Manager Data Types ~~~~~~~~~~ }
{ note: byte size fields don't work right in MacPascal }

  TPStr80 = ^TStr80;
  TStr80 = string[80];

  TPRect = ^Rect;

  TPPrPort = ^TPrPort;
  TPrPort = record
    gPort : GrafPort                            ;{ GrafPort to draw in 
}
    gProcs : QDProcs      ;{ pointers to drawing routines }
    LGParam1, LGParam2 : longint;
    LGParam3, LGParam4 : longint;        { internal use }
    {         fOurPtr:boolean }
    fOurBits : integer;                       { boolean }
   end;

  TPPort = record
    case integer of
     0 : (
       pGPort : GrafPtr
     );
     1 : (
       pPrPort : TPPrPort
     )
   end;

  TPrInfo = record
    iDev : INTEGER;                   {driver information}
    iVRes : INTEGER;             {printer vertical resolution}
    iHRes : INTEGER;             {printer horizontal resolution}
    rPage : Rect                         {page rectangle}
   end;

  TPrStl = record
    wDev : integer;                    {  TWord;  used internally}
    iPageV : INTEGER;           {paper height}
    iPageH : INTEGER;          {paper width}
{          bPort : SignedByte;  printer or modem port}
    Tfeed : integer;                   { TFeed;   paper type}
   end;

  TFeed = (feedCut, {hand-fed, individually cut sheets}
   feedFanfold,        {continuous-feed fanfold paper}
   feedMechCut,      {mechanically fed cut sheets}
   feedOther);         {other types of paper}

  TPrJob = record
    iFstPage : INTEGER;         {first page to print}
    iLstPage : INTEGER;         {last page to print}
    iCopies : INTEGER;            {number of copies}
    bJDocLoop : integer;
{  printing method (in upper byte)  }
{         fFromUsr :  BOOLEAN;  }
{ TRUE if called from application }
    pIdleProc : ProcPtr; {background procedure}
    pFileName : TPStr80; {spool file name}
    iFileVol : INTEGER; {volume reference number}
{         bFileVers : SignedByte;  }
{         version number of spool file }
    bJobX : integer;{ SignedByte  not used}
   end;

  TScan = (scanTB,   {scan top to bottom}
   scanBT,   {scan bottom to top}
   scanLR,    {scan left to right}
   scanRL);  {scan right to left}

  TPrXInfo = record
    iRowBytes : INTEGER; {bytes per row}
    iBandV : INTEGER; {vertical dots}
    iBandH : INTEGER; {horizontal dots}
    iDevBytes : INTEGER; {size of bit image}
    iBands : INTEGER; {bands per page}
{         bPatScale : SignedByte;  used by Quickdraw}
    bUlThick : integer;
{        was Signed Byte,  underline thickness}
{         bUlOffset : Signed Byte;  underline offset}
    bUlShadow : integer;
{        was SignedByte, underline descender}
    scan : integer;{ TScan(byte), scan direction }
{         bXInfoX : SignedByte  not used }
   end;

  THPrint = ^TPPrint;
  TPPrint = ^TPrint;
  TPrint = record
    iPrVersion : INTEGER; {Printing Manager version}
    prInfo : TPrInfo; {printer information}
    rPaper : Rect; {paper rectangle}
    prStl : TPrStl; {style information}
    prInfoPT : TPrInfo; {Pcopy of PrInfo}
    prXInfo : TPrXInfo; {band information}
    prJob : TPrJob; {job information}
    printX : array[1..19] of INTEGER
{ printX used internally by print manager}
   end;

  TPrStatus = record
    iTotPages : INTEGER; {total number of pages}
    iCurPage : INTEGER; {page being printed}
    iTotCopies : INTEGER; {number of copies}
    iCurCopy : INTEGER; {copy being printed}
    iTotBands : INTEGER; {bands per page}
    iCutBand : INTEGER; {band being printed}
{         fPgDirty : BOOLEAN; in lower byte of iCutBand }
{         dirty is TRUE if started printing page}
    fImaging : integer;{ BOOLEAN;  TRUE if imaging}
    hPrint : THPrint; {print record}
    pPrPort : TPPrPort; {printing port}
    hPic : PicHandle {used internally}
   end;


{ Parameter Block information contained in File Manager}
{ chapter of Inside Macintosh.  Note that MacPascal }
{ won 't do 8 bit fields right.  We will only use the }
{ ioParam part here }

  ParamBlkPtr = ^ParamBlockRec;
  ParamBlockRec = record
    qLink : Ptr;
    qType : integer;
    ioTrap : integer;
    ioCmdAddr : ptr;
    ioCompletion : ptr;
    ioResult : integer;
    ioNamePtr : ^str255;
    ioVrefNum : integer;
{  case ParamBlkType of  ...  ioParam:  }
    ioRefNum : integer;
  {       ioVersNum : byte;  }
    ioPermssn : integer;{ byte }
    ioMisc : ptr;
    ioBuffer : ptr;
    ioReqCount : longint;
    ioActCount : longint;
    ioPosMode : integer;
    ioPosOffset : longint;
   end;

 var  {-----------global variables-----------}
{ jsr and access are 68000 glue routines }
{ jsr source code described below }
{ See MacTutor vol.1 no.6 for access source code }
  jsr : array[0..3] of integer;
  access : array[0..12] of integer;
  ResId : integer;{ id of currently open Printer file }
  hPrint : THPrint;{ data record for print job }
  pPrPort : TPPrPort;{ pointer to port to draw into }
  PrStatus : TPrStatus;{ printing status record }
  page : integer;{ page number currently printing }
  pageR : rect;{ copy of rPaper rectangle }
  width : integer;{ width of paper }
  maxR : rect;{ huge rectangle }
  myport : GrafPtr;{ for temporary use }


{           %%%    %%%        %%          %%                     }
{           %   %    %   %     %      %    %      %                  
}
{           %%%    %%%     %      %    %                           }
{           %          % %       %      %    %      %                
  }
{           %          %   %        %%          %%                   
  }
{----------beginning of procedure definitions----------}

{ This loads, locks, dereferences, and computes an }
{ entry point for a resource that will be used as code }
 function GetAddress (id, offset : integer) : longint;
  var
   h, d : Handle;
 begin
  h := pointer(LinlineF($A9A0, $50444546, id));
{ _GetResource('PDEF',id) }
  d := nil;
  inlineP($4E75, @d, @H, $A029, @access);
{ _Hlock( H ) }
  if d <> nil then
   writeln('GetAddress error', ord(d));
  GetAddress := ord(h^) + offset;
 end;

{ This unlocks a PDEF resource that was locked to run }
 procedure ReleaseAddress (id : integer);
  var
   h, d : Handle;
 begin
  h := pointer(LinlineF($A9A0, $50444546, id));
{ _GetResource('PDEF',id) }
  d := nil;
  inlineP($4E75, @d, @H, $A02A, @access);
{ _Hunlock( H ) }
  if d <> nil then
   writeln('ReleaseAddress error', ord(d));
 end;

{ this calls GetAddress for the appropriate resource. }
{ Which resource is used depends upon bjDocLoop. }
 function MethodAdd (hPrint : THPrint;
         offset : integer) : longint;
  var
   method : integer;
 begin
  method := hPrint^^.prJob.bjDocLoop div 256;
  method := method mod 4;
  hPrint^^.prJob.bjDocLoop := method * 256;
{    bjDocLoop is in upper byte.  It must be mod 4 }
  MethodAdd := GetAddress(method, offset);
 end;

{common OS trap code, could be done with 'Generic' call}
{ see MacTutor vol.1 no.6 for source code }
 function filecall (Pb : ParamBlkPtr;
         trap : integer) : integer;
  var
   d0, a0 : longint;
 begin
  a0 := ord(pb);
  inlineP($4E75, @d0, @a0, trap, @access);
{ $4E75 is rts to access routine }
  filecall := loword(d0);
 end;

{ The following File Manager calls work just like   }
{ those described in Inside Macintosh for the Lisa Pascal }
{ Workshop, except that the async parameter is a }
{ dummy; all calls are sync. }

 function PBOpen (Pb : ParamBlkPtr;
         async : boolean) : integer;
 begin
  PBOpen := filecall(pb, $A000);
 end;

{ Below are the Printing Manager calls. }
{ They are supposed to work just like the real ones. }

 procedure PrOpen;
  var
   sH : strHan;
   pblock : ParamBlockRec;
   Tstr : str255;
 begin
  Tstr := '.Print';
  pBlock.ioNamePtr := @Tstr; { first we open driver...}
  pBlock.ioPermssn := 0;
  if PBOpen(@pBlock, false) <> 0 then
   sysbeep(100);
{...then we open the resource fork of current printer file}
  sH := pointer(LinlineF($A9BA, $E000));
{ _GetString(-8192 ) = name of print manager }
  ResId := WinlineF($A997, sH^);
{ _OpenResFile of print manager, usually='Imagewriter'}
 end;

 procedure PrClose;
 begin
  inlineP($A99A, ResId);{ _CloseResFile }
{    note that the driver is left open }
 end;


 procedure PrintDefault (hPrint : THPrint);
 begin
  inlineP($4E75, hPrint, Getaddress(4, 0), @jsr);
{ $4E75 is rts to 'jsr' routine which runs  }
{ PDEF #4 with offset of zero. }
{ This same sequence is used below also }
  ReleaseAddress(4);
 end;

 function PrValidate (hPrint : THPrint) : boolean;
 begin
  PrValidate := 
          BinlineF($4E75, hPrint, Getaddress(4, 24), @jsr);
  ReleaseAddress(4);
 end;

 function PrStlDialog (hPrint : THPrint) : boolean;
 begin
  PrStlDialog := 
            BinlineF($4E75, hPrint, Getaddress(4, 4), @jsr);
  ReleaseAddress(4);
 end;

 function PrJobDialog (hPrint : THPrint) : boolean;
 begin
  PrJobDialog := 
            BinlineF($4E75, hPrint, Getaddress(4, 8), @jsr);
  ReleaseAddress(4);
 end;

 procedure PrJobmerge (hPrintSrc, hPrintDst :       
                                                    THPrint);
 begin
  inlineP($4E75, hPrintSrc, hPrintDst, 
                                              Getaddress(4, 28), @jsr);
  ReleaseAddress(4);
 end;

 function PrOpenDoc (hPrint : THPrint;
         pPrPort : TPPrPort;
         pIOBuf : Ptr) : TPPrPort;
  var
   lll : longint;
 begin
  lll := LinlineF($4E75, hPrint, pPrPort, pIOBuf,
                                         MethodAdd(hPrint, 0), @jsr);
  PROpenDoc := pointer(lll);
 end;

 procedure PrOpenPage (pPrPort : TPPrPort;
         pPageFrame : TPRect);
 begin
  inlineP($4E75, pPrPort, pPageFrame, 
                                         MethodAdd(hPrint, 8), @jsr);
 end;

 procedure PrClosePage (pPrPort : TPPrPort);
 begin
  inlineP($4E75, pPrPort, MethodAdd(hPrint, 12), @jsr);
 end;

 procedure PrCloseDoc (pPrPort : TPPrPort);
 begin
  inlineP($4E75, pPrPort, MethodAdd(hPrint, 4), @jsr);
  ReleaseAddress(1);
 end;

 procedure PrPicFile (hPrint : THPrint;
         pPrPort : TPPrPort;
         pIOBuff : Ptr;
         pDevBuf : Ptr;
         var prStatus : TPrStatus);
 begin
  inlineP($4E75, hPrint, pPrPort, pIOBuff, pDevBuf, 
                              @prStatus, Getaddress(5, 0), @jsr);
  ReleaseAddress(5);
 end;

 function PrError : integer;
  var
   eptr : Ptr;
 begin
  eptr := pointer($944);
  PrError := eptr^;
 end;

 procedure PrSetError (iErr : integer);
  var
   eptr : Ptr;
 begin
  eptr := pointer($944);
  eptr^ := iErr;
 end;


{ This is my routine to draw a sample picture. }
{ The picture is drawn into the current port. }
{ Note that this is a very wide picture. }
 procedure drawpic;
  var
   i : integer;
   r : Rect;
 begin
  moveto(4, 220);
  textfont(2);
  textsize(216);{ must be less than 256 }
  textface([bold, outline, underline]);
  drawstring('Hooray for MacTutor!');
 end;

                           %%%%%%%                               }
{                                 %%%                                
     }
{                                    %                               
         }
{                 Main entry point of program                    }
begin  
 stuffHex(@jsr, '5488225F2F084ED1');
{ Code to jsr to address on top of stack: }

{ 5488  addq.l   #2,a0      ;a0 is now return address }
{ 225F  move.l  (a7)+,a1  ;a1 is address of routine }
{ 2F08  move.l  a0,-(sp)   ;put return on stack }
{ 4ED1  jmp       (a1)         ;and call routine }

 stuffHex(@access, '2848548C41FA000C309F245F265F20522013FFFF224826804ED4');
{ access calls a register based trap }

 showdrawing;{ Set current port to Drawing window. }
 setrect(maxR, 10, 100, 510, 330);
 SetDrawingRect(maxR);{ Make Drawing big. }
 setrect(maxR, -32000, -32000, 32000, 32000);
{  make maxR huge }

 cliprect(maxR); { Open up clip region. }
 for page := 0 to 8 do{ Draw 9 times for preview. }
  begin
   setOrigin(page * 300, 0);{ Use increasing offset. }
   eraserect(maxR);
   drawpic;{<------ Draw our picture in drawing. }
  end;

 hPrint := NewHandle(120);
{ 120 is size of TPrint record. }

 PrOpen;{ Open Printing Manager. }

 PrintDefault(hPrint);{ Fetch default hPrint. }

{ Now modify style info of hPrint if desired. }
{ For banner chose Wide and No Breaks Between Pages. }
 if PrStlDialog(hPrint) then
  writeln('new style chosen');

{ Then get job info for hPrint. }
 if PrJobDialog(hPrint) then
  begin
   pPrPort := PrOpenDoc(hPrint, nil, nil);
{ Grafport is now pPrPort, not Drawing window. }

   pageR := hPrint^^.prInfoPt.Rpage;
   pageR.right := pageR.right div 2;
   pageR.bottom := pageR.bottom div 2;
   width := pageR.right;{ width of printing 'window' }
{ Draw into rect 1/2 page size, quickdraw will }
{ scale picture to fit page later. This effectivly doubles}
{ the size of our drawing. }

{ Now we will draw the picture. It will go into pPrPort. }
{ For each page we offset to clip off parts not used. }
   getport(myport);{ myport := pPrPort; }
   for page := 0 to 7 do{ 8 pages }
    begin
     PrOpenPage(pPrPort, @pageR);
{ PrOpenPage resets the ports size, coordinates etc. }

     setOrigin(width * page, 0);

{ setOrigin does not change cliprgn so we do it here. }
     offsetRgn(myport^.cliprgn, width * page, 0);
{ I tried simply maxing out the clip and it didn't work. }

     drawpic;{<---------draw picture into pPrPort}

     PrClosePage(pPrPort);
    end;

   PrCloseDoc(pPrPort);

   PrPicFile(hPrint, nil, nil, nil, PrStatus);
  end;{ if job }

 disposeHandle(hPrint);
 PrClose;
end.
 

Community Search:
MacTech Search:

Software Updates via MacUpdate

Deeper 2.2.1 - Enable hidden features in...
Deeper is a personalization utility for macOS which allows you to enable and disable the hidden functions of the Finder, Dock, QuickTime, Safari, iTunes, login window, Spotlight, and many of Apple's... Read more
Spotify 1.0.59.395. - Stream music, crea...
Spotify is a streaming music service that gives you on-demand access to millions of songs. Whether you like driving rock, silky R&B, or grandiose classical music, Spotify's massive catalogue puts... Read more
FileZilla 3.27.0.1 - Fast and reliable F...
FileZilla (ported from Windows) is a fast and reliable FTP client and server with lots of useful features and an intuitive interface. Version 3.27.0.1: MSW: Add misssing file to .zip binary package... Read more
Sierra Cache Cleaner 11.0.6 - Clear cach...
Sierra Cache Cleaner is an award-winning general purpose tool for macOS X. SCC makes system maintenance simple with an easy point-and-click interface to many macOS X functions. Novice and expert... Read more
Live Home 3D Pro 3.1.2 - $69.99
Live Home 3D Pro, a successor of Live Interior 3D, is the powerful yet intuitive home design software that lets you build the house of your dreams right on your Mac. It has every feature of Live Home... Read more
Pinegrow 3.04 - Mockup and design webpag...
Pinegrow (was Pinegrow Web Designer) is desktop app that lets you mockup and design webpages faster with multi-page editing, CSS and LESS styling, and smart components for Bootstrap, Foundation,... Read more
DiskCatalogMaker 7.1.2 - Catalog your di...
DiskCatalogMaker is a simple disk management tool which catalogs disks. Simple, light-weight, and fast Finder-like intuitive look and feel Super-fast search algorithm Can compress catalog data for... Read more
Apple iTunes 12.6.2 - Play Apple Music a...
Apple iTunes lets you organize and stream Apple Music, download and watch video and listen to Podcasts. It can automatically download new music, app, and book purchases across all your devices and... Read more
Transmit 5.0 - Excellent FTP/SFTP client...
Transmit is an excellent FTP (file transfer protocol), SFTP, S3 (Amazon.com file hosting) and iDisk/WebDAV client that allows you to upload, download, and delete files over the internet. With the... Read more
Adobe Lightroom 6.12 - Import, develop,...
Adobe Lightroom is available as part of Adobe Creative Cloud for as little as $9.99/month bundled with Photoshop CC as part of the photography package. Lightroom 6 is also available for purchase as a... Read more

Latest Forum Discussions

See All

The best deals on the App Store this wee...
There are quite a few truly superb games on sale on the App Store this week. If you haven't played some of these, many of which are true classics, now's the time to jump on the bandwagon. Here are the deals you need to know about. [Read more] | Read more »
Realpolitiks Mobile (Games)
Realpolitiks Mobile 1.0 Device: iOS Universal Category: Games Price: $5.99, Version: 1.0 (iTunes) Description: PLEASE NOTE: The game might not work properly on discontinued 1GB of RAM devices (iPhone 5s, iPhone 6, iPhone 6 Plus, iPad... | Read more »
Layton’s Mystery Journey (Games)
Layton’s Mystery Journey 1.0.0 Device: iOS Universal Category: Games Price: $15.99, Version: 1.0.0 (iTunes) Description: THE MUCH-LOVED LAYTON SERIES IS BACK WITH A 10TH ANNIVERSARY INSTALLMENT! Developed by LEVEL-5, LAYTON’S... | Read more »
Full Throttle Remastered (Games)
Full Throttle Remastered 1.0 Device: iOS Universal Category: Games Price: $4.99, Version: 1.0 (iTunes) Description: Originally released by LucasArts in 1995, Full Throttle is a classic graphic adventure game from industry legend Tim... | Read more »
Stunning shooter Morphite gets a new tra...
Morphite is officially landing on iOS in September. The game looks like the space shooter we've been needing on mobile, and we're going to see if it fits the bill quite shortly. The game's a collaborative effort between Blowfish Studios, We're Five... | Read more »
Layton's Mystery Journey arrives to...
As you might recall, Layton's Mystery Journey is headed to iOS and Android -- tomorrow! To celebrate the impending launch, Level-5's released a new trailer, complete with an adorable hamster. [Read more] | Read more »
Sidewords (Games)
Sidewords 1.0 Device: iOS Universal Category: Games Price: $2.99, Version: 1.0 (iTunes) Description: Grab a cup of coffee and relax with Sidewords. Sidewords is part logic puzzle, part word game, all original. No timers. No... | Read more »
Noodlecake Games' 'Leap On!...
Noodlecake Games is always good for some light-hearted arcade fun, and its latest project, Leap On! could carry on that tradition. It's a bit like high stakes tetherball in a way. Your job is to guide a cute little blob around a series of floating... | Read more »
RuneScape goes mobile later this year
Yes, RuneScape still exists. In fact, it's coming to iOS and Android in just a few short months. Jagex, creators of the hit fantasy MMORPG of yesteryear, is releasing RuneScape Mobile and Old School RuneScape for mobile devices, complete with... | Read more »
Crash of Cars wants you to capture the c...
Crash of Cars is going full on medieval in its latest update, introducing castles and all manner of new cars and skins fresh from the Dark Ages. The update introduces a new castle-themed map (complete with catapults) and a gladiator-style battle... | Read more »

Price Scanner via MacPrices.net

Save or Share
FotoJet Designer, is a simple but powerful new graphic design apps available on both Mac and Windows. With FotoJet Designer’s 900+ templates, thousands of resources, and powerful editing tools you... Read more
Logo Maker Shop iOS App Lets Businesses Get C...
A newly released app is designed to help business owners to get creative with their branding by designing their own logos. With more than 1,000 editable templates, Logo Maker Shop 1.0 provides the... Read more
Sale! New 15-inch MacBook Pros for up to $150...
Amazon has the new 2017 15″ MacBook Pros on sale for up to $150 off MSRP including free shipping: – 15″ 2.8GHz MacBook Pro Space Gray: $2249 $150 off MSRP – 15″ 2.89Hz MacBook Pro Space Gray: $2779 $... Read more
DEVONthink To Go 2.1.7 For iOS Brings Usabili...
DEVONtechnologies has updated DEVONthink To Go, the iOS companion to DEVONthink for Mac, with enhancements and bug fixes. Version 2.1.7 adds an option to clear the Global Inbox and makes the grid... Read more
15-inch 2.2GHz Retina MacBook Pro, Apple refu...
Apple has Certified Refurbished 2015 15″ 2.2GHz Retina MacBook Pros available for $1699. That’s $300 off MSRP, and it’s the lowest price available for a 15″ MacBook Pro. An Apple one-year warranty is... Read more
13-inch 2.3GHz Silver MacBook Pro on sale for...
B&H Photo has the new 2017 13″ 2.3GHz/256GB Silver MacBook Pro (MPXU2LL/A) on sale for $1399 including free shipping plus NY & NJ sales tax only. Their price is $100 off MSRP. Read more
Apple Tackles Distracted Driving With iOS 11...
One of the most important new features coming in iOS 11 is Do Not Disturb while driving, intended to help drivers stay more focused on the road. With Do Not Disturb while driving, your iPhone can... Read more
iMazing Mini for Mac: Free Automatic and Priv...
Geneva, Switzerland-based indie developer DigiDNA has released iMazing Mini, their free macOS utility designed to automatically back up iOS devices over any local Wi-Fi network. The app offers users... Read more
Clearance 2016 13-inch MacBook Airs, Apple re...
Apple dropped prices recently on Certified Refurbished 2016 13″ MacBook Airs, with models now available starting at $809. An Apple one-year warranty is included with each MacBook, and shipping is... Read more
9.7-inch 2017 iPads available for $299, save...
B&H Photo has 2017 9.7″ 32GB WiFi iPads on sale for $30 off MSRP for a limited time. Shipping is free, and pay sales tax in NY & NJ only: – 32GB iPad WiFi: $299, $30 off Read more

Jobs Board

*Apple* Retail - Multiple Positions - Apple...
SalesSpecialist - Retail Customer Service and SalesTransform Apple Store visitors into loyal Apple customers. When customers enter the store, you're also the Read more
Senior Payments Architect - *Apple* Pay - A...
Changing the world is all in a day's work at Apple . If you love innovation, here's your chance to make a career of it. You'll work hard. But the job comes with more Read more
Frameworks Engineering Manager, *Apple* Wat...
Frameworks Engineering Manager, Apple Watch Job Number: 41632321 Santa Clara Valley, California, United States Posted: Jun. 15, 2017 Weekly Hours: 40.00 Job Summary Read more
Manager, *Apple* Media Products - Apple Inc...
Job Summary The Apple Media Products Discovery, Fraud and Abuse team is responsible for protecting the integrity of Apple services. As a manager of the team, you Read more
*Apple* Watch, Accessories, Engineering Proj...
Job Summary Engineering Project Manager, Apple Watch Accessories. The Accessories group is looking for an Engineering Project Manager (EPM) to lead the design and Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.