TweetFollow Us on Twitter

Aug 99 Getting Started

Volume Number: 15 (1999)
Issue Number: 8
Column Tag: Getting Started

Printing

By Dan Parks Sydow

How a Mac program sends document data to a printer

In the previous few Getting Started articles we've focused on the use of files to provide users of your Macintosh applications with the means to save program output. This month we'll look at a second data-saving technique - printing. By adding printing capabilities to your program, both text and graphics can be sent to any printer that's attached to the user's computer.

Printing Basics

In this article you'll see how to write a program that displays the two standard printing dialog boxes found in most Mac programs. The Printing Style dialog box, shown in Figure 1, allows the user to select page preferences such as page orientation. The Printing Job dialog box, pictured in Figure 2, lets the user specify the print quality and the page range. For reasons explained ahead, the dialog boxes you see on your Mac may look somewhat different than the ones shown here.



Figure 1.A typical Printing Style dialog box.



Figure 2.A typical Printing Job dialog box.

Your program can display both the Printing Style and Printing Job dialog boxes through the use of Printing Manager routines. Like other Toolbox managers, the Printing Manager is a collection of system software routines. Unlike the other managers, the code that makes up each Printing Manager routine isn't found in ROM or in the System File. Rather, the Toolbox printing routines are nothing more than empty shells, or stub routines. When your application makes a call to a Toolbox printing function, the program is directed to code that exists in a printer resource file. Printer resource files enable the Printing Manager to work with all printers that come with a Macintosh printer driver.

When an application calls a routine from a manager other than the Printing Manager, the program jumps to Toolbox code that originates in ROM or in the System File. The code that makes up that one routine - whatever routine it is - is then carried out. If the call is to, say, Line(100, 0), QuickDraw draws a line 100 pixels long to the current port. This is true regardless of the kind of monitor hooked up to the Mac. For printers, this “one generic code works on all” principle doesn't apply. There are countless third-party printers that can be hooked up to a Macintosh, and no uniform standard of how Toolbox calls should be handled by a printer. So Apple leaves it up to the manufacturer of each printer to supply the code that makes the printing functions work. This code is found in the printer resource file that accompanies a printer that is Mac-compatible.

Every printer that works with a Macintosh comes supplied with a printer resource file. This file, which is placed in the Extensions folder in the System Folder, holds the code that actually carries out Printing Manager routines. The file, which has a name that often includes the name of the printer, must be present in order for the printer to function. Since each type of printer has its own printer resource file, and since a Macintosh can have more than one printer connected to it, a Mac can have more than one printer resource file. The printer (and thus the printer resource file) that a Macintosh uses is governed by the Chooser program found under the Apple menu.

The printer resource file holds resources of several types. Resources of type PDEF are printer definition functions - they hold the compiled code that executes when a Printing Manager function is called. When a Mac application makes a call to a Printing Manager routine the call is routed to the printer resource file. There, the code that makes up one of the many PDEF resources is loaded and executed. By having each printer manufacturer support all the same Printing Manager routines, the burden of worrying about which printer is connected to a user's system is lifted from the Macintosh software developer. When you write an application that calls Printing Manager routines, you won't have to consider the type of printer that any one user might have. Instead, just make the function call. It will be up to the printer resource file to handle that function call as is appropriate for that printer.

Printing Manager Basics

Like all of the Toolbox managers, the Printing Manager consists of a wealth of functions. But to get started with printing, you'll need to use only a handful of them.

The Print Record

Before printing, your application must create a print record. This record holds information specific to the printer being used, such as its resolution, and information about the document that is to be printed, such as scaling, page orientation, and the number of copies to print.

In C, the print record is represented by a struct of the type TPrint. Before any printing takes place, your application must allocate memory for a TPrint structure and obtain a handle - a THPrint handle - to that memory. By the way, the T in THPrint stands for type, and the H stands for handle - you'll see this notation used throughout the functions of the Printing Manager. You can make a call to the Memory Manager routine NewHandle() or NewHandleClear() to reserve the needed memory and to receive a handle to that memory. Include the size of a print record as the parameter and cast the returned generic pointer to a THPrint handle.

THPrint	printRecord;
printRecord = (THPrint)NewHandleClear( sizeof (TPrint) );

After creating a new print record, call the Printing Manager routine PrintDefault() to fill the record with default values. These values will serve as initial values until the user selects Page Setup and Print from the File menu of your application. The values entered in the corresponding dialog boxes will overwrite some or all of the values supplied by PrintDefault().

PrintDefault( printRecord );

Printing Manager Functions

Knowledge of less than a dozen Printing Manager functions is all that's needed to get your Mac application printing. As you read this section, note that each of the three Open functions is paired with a Close function: calls to PrOpen(), PrOpenDoc(), and PrOpenPage() are balanced with calls to PrClose(), PrCloseDoc() and PrClosePage(), respectively.

The code to execute Printing Manager functions resides in a resource file, so your program needs to open this resource file before its code can be accessed. The Printing Manager function PrOpen() prepares the current printer resource file for use. The current printer is whichever printer was last selected in the Chooser. Preparation consists of opening both the Printing Manager and the printer resource file for the current printer. When finished with the resource file, a call to PrClose() closes the Printing Manager and the printer resource file.

PrOpen();
// printing-related code here
PrClose();

PrOpenDoc() initializes a printing graphics port. This graphics port isn't associated with any window - it's associated with the printer. When a window's graphics port is current (by way of a call to SetPort()), drawing takes place on the screen. When a printing graphics port is current (by way of a call to PrOpenDoc()), drawing operations are routed to the printer. Once a printing graphics port is current, all QuickDraw commands are sent to the printer.

When passed a handle to a print record, PrOpenDoc() allocates a new printing graphics port and returns a TPPrPort to the application. The TPPrPort is a pointer to a printing graphics port. PrOpenDoc() requires a second and third parameter, each of which can normally be set to nil. The second parameter can be used when an application wants to pass in a pointer to an existing printing graphics port, and the third parameter can be used to allocate a particular area in memory to serve as an input and output buffer.

PrCloseDoc() closes a printing graphics port. Make a single call to PrCloseDoc() after the last page of a document has been sent to the printer. Pass PrCloseDoc() the pointer to the printing graphics port that was returned by PrOpenDoc().

TPPrPort	printerPort;
printerPort = PrOpenDoc( printRecord, nil, nil );
// print page(s) here
PrCloseDoc( printerPort );

PrOpenPage() is used to begin printing a single page of a document. Pass PrOpenPage() the pointer to the printing graphics port that was obtained in the PrOpenDoc() call. The second parameter is used only for deferred printing - a delayed printing feature that is normally used only on older printers. You can usually set this parameter to nil. After a call to PrOpenPage() is made, all the QuickDraw commands necessary to output one page of a document should be made. After that, call PrClosePage().

PrClosePage() signals the end of the current page. Once a call to PrClosePage() is made, the Printing Manager will stop accumulating QuickDraw calls. PrClosePage() requires a single parameter - the pointer to the printing graphics port that was returned by PrOpenDoc().

PrOpenPage( printerPort, nil );
// QuickDraw calls that define what's to be printed
PrClosePage( printerPort );  

Before printing, you'll want to give the user the opportunity to specify printing style options. A call to PrStlDialog() displays a Printing Style dialog box that allows the user to do just that. If your application has a Page Setup menu item, make a call to PrStlDialog() in response to a user's selection of this menu item. The Printing Style dialog box is defined in the resource file of the printer driver, so its exact look is dependent on the printer in use - this is why a Printing Style dialog box that you view may not look just like the one shown back in Figure 1.

The PrStlDialog() function requires a handle to a TPrint record as its one parameter. If the user clicks the Printing Style dialog box OK button, the values entered in that dialog box (such as page orientation) will be placed in the TPrint record. PrStlDialog() will then return a value of true. If the user clicks the Cancel button, the TPrint record will be unaffected and the routine will return a value of false.

PrStlDialog( printRecord );

Displaying the Printing Style dialog box saves document printing information, but not the number of copies or the range of pages to print. To do that, call PrJobDialog(). This routine will display the Printing Job dialog box. Like the Printing Style dialog box, the look of the Printing Job dialog box is defined in the printer resource file. A call to PrJobDialog() should be made in response to a user's selection of the Print menu item in your application.

PrJobDialog() accepts a handle to a TPrint record as its only parameter. A mouse click on the OK button results in the values in the dialog box (such as number of copies to print) being entered into the TPrint record. PrJobDialog() then returns a value of true to the application. A click on the Cancel button leaves the TPrint record untouched and returns a value of false to the program.

Boolean		doPrint;
doPrint = PrJobDialog( printRecord );
if ( doPrint == false )
	// handle case of user canceling printing

PrintPict

This month's program is PrintPict. To provide you with a very concise, straightforward example of the primary functions of the Printing Manager, PrintPict is a simple, non-menu-driven program. When run, PrintPict displays the Printing Style dialog box - the dialog box normally brought on by choosing Page Setup from the File menu. After clicking the OK button, the program dismisses that dialog box and displays the Printing Job dialog box - the dialog box normally brought on by choosing Print from the File menu. After clicking the Print button, the program dismisses that dialog box and sends the printing job to the printer. After that the program quits. Without menus and without giving the user any control of what to print, the PrintPict program certainly doesn't qualify as user-friendly. But, much more importantly, it does show you, in just a page or two of code, how to make use of the Printing Manager.

Creating the PrintPict Resources

Start the project by creating a new folder named PrintPict in your CodeWarrior development folder. Launch ResEdit, then create a new resource file named PrintPict.rsrc. Make sure to specify the PrintPict folder as the resource file's destination. The resource file will hold resources of the types shown in Figure 3.



Figure 3.The PrintPict resources.

The one ALRT and one DITL resource are used to define the program's error-handling alert. The only other resource needed is a single PICT. It's this picture that will be printed by the PrintPict program. Feel free to use any picture of any reasonable size here. If you have a color printer, go ahead and include a color picture so that you can verify that the PrintPict program prints in color.

Creating the PrintPict Project

Start CodeWarrior and choose New Project from the File menu. Use the MacOS:C_C++:MacOS Toolbox:MacOS Toolbox Multi-Target project stationary for the new project. You've already created a project folder, so uncheck the Create Folder check box before clicking the OK button. Name the project PrintPict.mcp, and make sure the project's destination is the PrintPict folder.

Add the PrintPict.rsrc resource file to the new project. Remove the SillyBalls.rsrc file. Go ahead and remove the ANSI Libraries folder from the project window if you want - the project doesn't use any of these libraries.

Create a new source code window by choosing New from the File menu.. Save the window, giving it the name PrintPict.c. Now choose Add Window from the Project menu to add this empty file to the project. Remove the SillyBalls.c placeholder file from the project window. You're all set to type in the source code.

To save yourself some typing, go to MacTech's ftp site at ftp://ftp.mactech.com/src/mactech/volume15_1999/15.08.sit. There you'll find the PrintPict source code file available for downloading.

Walking Through the Source Code

Because the PrintPict program isn't event-driven, the listing is shorter than our other example listings. PrintPict.c starts with a couple of constants. kALRTResID defines the ID of the ALRT resource used to define the error-handling alert. kPICTResID defines the ID of the PICT resource that holds the picture to print.

/********************* constants *********************/
#define 		kALRTResID			128
#define		kPICTResID			128

PrintPict declares just one global variable. The THPrint variable gPrintRecord is the print record that holds information about the currently selected printer. While in PrintPict we could get away with declaring this variable local to main(), it's been declared global for future use. If we expand upon the PrintPict program we'll put the print record to use in a variety of routines. For instance, if we later implement a File menu that includes a Print item, then the display of the printing job dialog box will no doubt be handled by a separate application-defined function. A call to PrJobDialog() requires the print record as a parameter.

/****************** global variables *****************/
THPrint		gPrintRecord;

Next come the program's function prototypes.

/********************* functions *********************/
void		ToolBoxInit( void );
void		DrawToPort( void );
void		DoError( Str255 errorString );

The main() function begins with the declaration of a couple of variables. The TPPrPort variable printerPort is a pointer to a printing graphics port. This variable will get its value from a call to PrOpenDoc(). The Boolean variable doPrint tells the program whether the Printing Job dialog box was dismissed with a click on the Print or the Cancel button. Next, the Toolbox is initialized by way of a call to ToolBoxInit().

/********************** main *************************/
void		main( void )
{
	TPPrPort		printerPort;
	Boolean		doPrint;
	ToolBoxInit();

A new print record is then created. A call to PrOpen() prepares the current printer resource file for use. PrintDefault() fills the new print record with default values.

	gPrintRecord = (THPrint)NewHandleClear( sizeof( TPrint ) );
	PrOpen();
	PrintDefault( gPrintRecord );

Next, the Printing Style dialog box is displayed. The call to PrStlDialog() does all the work of monitoring the user's actions in this dialog box. In a full-featured program we'd make this call in response to the user choosing Page Setup from the File menu.

	PrStlDialog( gPrintRecord );

Once the Printing Style dialog box is dismissed, a call to PrJobDialog() displays the Printing Job dialog box. If the user clicks the Print button, PrJobDialog() returns a value of true, and the program continues on. If the user cancels printing, the program ends. In your own application you won't need to abruptly exit should the user cancel printing - you'll typically just carry on.

	doPrint = PrJobDialog( gPrintRecord );
	if ( doPrint == false )
		DoError( "\pUser canceled printing" );

If printing is to take place, the program calls PrOpenDoc() to initialize a printing graphics port. A pointer to the new port is returned and saved in the variable printerPort.

	printerPort = PrOpenDoc( gPrintRecord, nil, nil );

A call to PrOpenPage() begins the printing of a page. After this call all subsequent QuickDraw commands are routed to the printer. While the QuickDraw calls could have appeared here in main(), we'll group them in an application-defined function named DrawToPort().

	PrOpenPage( printerPort, nil );
	DrawToPort( kPICTResID );

We'll look at DrawToPort() just ahead. Regardless of the contents of that routine, once DrawToPort() returns, the printing of a page is complete - so we can wrap things up. A call to PrClosePage() balances the previous call to PrOpenPage(). Similarly, a call to PrCloseDoc() balances the prior call to PrOpenDoc(). Finally, a call to PrClose() pairs with the earlier call to PrOpen(), and closes the Printing Manager and the printing resource file.

	PrClosePage( printerPort );  
	PrCloseDoc( printerPort );
	PrClose();
}

As expected, ToolBoxInit() is identical to previous versions.

/******************** ToolBoxInit ********************/
void		ToolBoxInit( void )
{
	InitGraf( &qd.thePort );
	InitFonts();
	InitWindows();
	InitMenus();
	TEInit();
	InitDialogs( nil );
	InitCursor();
}

The DrawToPort() function holds the code that defines what is to be printed. PrintPict prints a picture, so the code in DrawToPort() loads a PICT resource to memory and then draws that picture. A call to GetPicture() moves the PICT code to memory.

void DrawToPort( void )
{
 	PicHandle	pict;
	Rect				rect;
	short			width;
	short			height;
	short			L, R, T, B;
	pict = GetPicture( kPICTResID );

Next, the size of the picture is determined. The picFrame field of the picture record referenced by the handle pict supplies that information. A little offsetting is done in case the picFrame rectangle boundaries aren't located at (0, 0).

	rect = (**pict).picFrame;
	width = rect.right - rect.left;
	height = rect.bottom - rect.top;

Now we determine where on the page we want the picture printed. The upper-left corner of the page is at coordinate (0, 0). By setting up a rectangle with a upper-left coordinate at (75, 50) we're telling the program to start the picture 75 pixels from the left of the page and 50 pixels from the top of the page.

	L = 75;
	R = L + width;
	T = 50;
	B = T + height;
	SetRect( &rect, L, T, R, B );

A call to DrawPicture() draws the picture. The current port has been set to the printer, so that's where "drawing" takes place. Finally, a call to ReleaseResource() frees the memory occupied by the picture.

	DrawPicture( pict, &rect ); 
	ReleaseResource( (Handle)pict );
} 

We've placed all the printing code in this one function for a good reason - it makes it easy to experiment. After successfully compiling and running the program you may want to replace the contents of DrawToPort() with other QuickDraw calls, such as a few calls to MoveTo() and Line(). Calls to DrawString() work too. DoError() is unchanged from prior versions. A call to this function results in the posting of an alert that holds an error message. After the alert is dismissed the program ends.

/********************** DoError **********************/
void		DoError( Str255 errorString )
{
	ParamText( errorString, "\p", "\p", "\p" );
	StopAlert( kALRTResID, nil );
	ExitToShell();
}

Running PrintPict

Run PrintPict by selecting Run from CodeWarrior's Project menu. After compiling the code and building a program, CodeWarrior runs the program. The Printing Style dialog box will automatically open. Look it over, make some changes if you'd like (including scaling the size of the picture), then click the OK button. After the style dialog box is dismissed, the Printing Job dialog box appears. Click the Print button and the dialog box is dismissed. The program quits, and a short time later your printer prints out a picture.

Till Next Month...

The PrintPict program provides a look at the very basics of sending information to a printer. Use your newfound knowledge of the Printing Manager to add Page Setup and Print commands to your program's File menu. In response to a print command you'll want to send the information from the frontmost window to the printer. Your program should already hold the code necessary to update a window, so your program already contains most of the code necessary to print! When a print command is issued, you'll specify that the port to "draw" to should be the printer - not the window. For the details on how to do this, browse through the Imaging With QuickDraw volume of Inside Macintosh. Or, wait until next month's issue of MacTech...

 
AAPL
$106.98
Apple Inc.
-0.36
MSFT
$46.05
Microsoft Corpora
-0.57
GOOG
$550.31
Google Inc.
+0.98

MacTech Search:
Community Search:

Software Updates via MacUpdate

Cocktail 8.0.1 - General maintenance and...
Cocktail is a general purpose utility for OS X that lets you clean, repair and optimize your Mac. It is a powerful digital toolset that helps hundreds of thousands of Mac users around the world get... Read more
LibreOffice 4.3.3.2 - Free Open Source o...
LibreOffice is an office suite (word processor, spreadsheet, presentations, drawing tool) compatible with other major office suites. The Document Foundation is coordinating development and... Read more
VMware Fusion 7.0.1 - Run Windows apps a...
VMware Fusion allows you to create a Virtual Machine on your Mac and run Windows (including Windows 8.1) and Windows software on your Mac. Run your favorite Windows applications alongside Mac... Read more
OneNote 15.3.2 - Free digital notebook f...
OneNote is your very own digital notebook. With OneNote, you can capture that flash of genius, that moment of inspiration, or that list of errands that's too important to forget. Whether you're at... Read more
Audio Hijack Pro 2.11.4 - Record and enh...
Audio Hijack Pro drastically changes the way you use audio on your computer, giving you the freedom to listen to audio when you want and how you want. Record and enhance any audio with Audio Hijack... Read more
Iridient Developer 3.0.0 beta 3 - Powerf...
Iridient Developer (was RAW Developer) is a powerful image conversion application designed specifically for OS X. Iridient Developer gives advanced photographers total control over every aspect of... Read more
TextWrangler 4.5.11 - Free general purpo...
TextWrangler is the powerful general purpose text editor, and Unix and server administrator's tool. Oh, and also, like the best things in life, it's free. TextWrangler is the "little brother" to... Read more
NeoFinder 6.6 - Catalog your external me...
NeoFinder (formerly CDFinder) rapidly organizes your data, either on external or internal disks, or any other volumes. It catalogs all your data, so you stay in control of your data archive or disk... Read more
Chromium 38.0.2125.111 - Fast and stable...
Chromium is an open-source browser project that aims to build a safer, faster, and more stable way for all Internet users to experience the web. FreeSMUG-Free OpenSource Mac User Group build is... Read more
Default Folder X 4.6.11 - Enhances Open...
Default Folder X attaches a toolbar to the right side of the Open and Save dialogs in any OS X-native application. The toolbar gives you fast access to various folders and commands. You just click... Read more

Latest Forum Discussions

See All

Night Sky Pro™ (Reference)
Night Sky Pro™ 3.0.1 Device: iOS Universal Category: Reference Price: $2.99, Version: 3.0.1 (iTunes) Description: Night Sky Pro™Wonder No More™ Night Sky Pro™ is the ultimate stargazing experience. From the creators of the original... | Read more »
Audio Defence : Zombie Arena (Games)
Audio Defence : Zombie Arena 1.0 Device: iOS Universal Category: Games Price: $4.99, Version: 1.0 (iTunes) Description: A zombie shooter audio game. Made from gut-wrenching 3D binaural sound, for a new kind of weird immersion. You... | Read more »
RPG Asdivine Hearts (Games)
RPG Asdivine Hearts 1.1.0 Device: iOS Universal Category: Games Price: $3.99, Version: 1.1.0 (iTunes) Description: SPECIAL PRICE50% OFF (USD 7.99 -> USD 3.99)!!! Travel alongside four companions and a cat in the adventure of a... | Read more »
Haunt the House: Terrortown (Games)
Haunt the House: Terrortown 1.0.1 Device: iOS Universal Category: Games Price: $.99, Version: 1.0.1 (iTunes) Description: 66.6% OFF! SPECIAL SPOOKY HALLOWEEN LAUNCH PRICE! 66.6% OFF! ...What was that sound? Is somebody there? | Read more »
SAS: Zombie Assault 4 Review
SAS: Zombie Assault 4 Review By Jennifer Allen on October 30th, 2014 Our Rating: :: FLAWED SHOOTERUniversal App - Designed for iPhone and iPad Shoot everything that moves in this fun, if flawed, twin-stick shooter.   | Read more »
Naailde the Witch Review
Naailde the Witch Review By Amy Solomon on October 30th, 2014 Our Rating: :: PITCH-PERFECT STORYTELLINGUniversal App - Designed for iPhone and iPad Marvelous storytelling, narration, and moving illustrations make this storybook... | Read more »
1st & Goal Review
1st & Goal Review By Andrew Fisher on October 30th, 2014 Our Rating: :: FOR THE D&D LOVING QBUniversal App - Designed for iPhone and iPad 1st & Goal is a board gamer’s football game, a football fan’s board game, and... | Read more »
French Developer Pated Unveils Seashine
French Developer Pated Unveils Seashine Posted by Ellis Spice on October 30th, 2014 [ permalink ] French one-man studio Pated has unveiled Seashine, “a poetic journey into the abyss.” Players take on the role of a jellyfish strugglin | Read more »
Agents of Storm: Tips, Tricks, and Strat...
Calling all agents: Would you like to see what we thought of this rather pretty base builder? Check out our Agents of Storm review! Have you downloaded Agents of Storm, been bowled over by the graphics, and aren’t quite sure what to do next? Never... | Read more »
Any.DO 2.0 Hopes to Help Manage Producti...
Any.DO 2.0 Hopes to Help Manage Productivity Posted by Ellis Spice on October 30th, 2014 [ permalink ] iPhone App - Designed for the iPhone, compatible with the iPad | Read more »

Price Scanner via MacPrices.net

Apple Regains Momentum As Windows Stutters An...
The latest smartphone sales data from Kantar Worldpanel ComTech, for the three months to March 2014, shows Apple performing strongly in the first quarter of the year, with sales bouncing back in... Read more
Worldwide Smartphone Shipments Increase 25.2%...
New smartphone releases and an increased emphasis on emerging markets drove global smartphone shipments above 300 million units for the second consecutive quarter, according to preliminary data from... Read more
Apple now offering refurbished 2014 15-inch M...
The Apple Store is now offering Apple Certified Refurbished 2014 15″ Retina MacBook Pros for up to $400 off the cost of new models. An Apple one-year warranty is included with each model, and... Read more
Apple drops prices on refurbished 2013 Retina...
The Apple Store has dropped prices on 2013 Apple Certified Refurbished 13″ and 15″ Retina MacBook Pros, with Retina models now available starting at $999. Apple’s one-year warranty is standard, and... Read more
New 2.8GHz Mac mini on sale for $949, save $5...
Abt Electronics has the new 2.8GHz Mac mini in stock and on sale for $949.05 including free shipping. Their price is $50 off MSRP, and it’s the lowest price available for this model from any reseller... Read more
Sale! 3.7GHz Quad Core Mac Pro available for...
 B&H Photo has the 3.7GHz Quad Core Mac Pro on sale for $2649 including free shipping plus NY sales tax only. Their price is $350 off MSRP, and it’s the lowest price for this model from any... Read more
Mujjo Steps Up The Game With Refined Touchscr...
Netherlands based Mujjo have just launched their Refined Touchscreen Gloves, stepping up their game. The gloves feature a updated elegant design that takes these knitted gloves to the next level. A... Read more
Sale! Preorder the new 27-inch 5K iMac for $2...
 Abt Electronics has the new 27″ 3.5GHz 5K iMac on sale and available for preorder for $2374.05 including free shipping. Their price is $125 off MSRP, and it’s the lowest price available for this... Read more
Simplex Solutions Inc. Brings Secure Web Surf...
New York based Simplex Solutions Inc. has announced the release and immediate availability of Private Browser 1.0, its revolutionary new secure web browser developed for iPhone, iPad and iPod touch... Read more
Save up to $180 off MSRP with an Apple refurb...
The Apple Store has Apple Certified Refurbished 2014 MacBook Airs available for up to $180 off the cost of new models. An Apple one-year warranty is included with each MacBook, and shipping is free.... Read more

Jobs Board

Position Opening at *Apple* - Apple (United...
**Job Summary** Every day, business customers come to the Apple Store to discover what powerful, easy-to-use Apple products can do for them. As a Business Leader, Read more
Sr. Manager, *Apple* Deployment Programs fo...
**Job Summary** Apple is seeking candidates for a new position on the Education Content and Technology team. iPad and Mac is in the hands of millions of teachers and Read more
*Apple* Solutions Consultant (ASC) - Apple I...
…important role that the ASC serves is that of providing an excellent Apple Customer Experience. Responsibilities include: * Promoting Apple products and solutions Read more
*Apple* Solutions Consultant (ASC) - Apple I...
…important role that the ASC serves is that of providing an excellent Apple Customer Experience. Responsibilities include: * Promoting Apple products and solutions Read more
*Apple* Solutions Consultant (ASC) - Apple I...
…important role that the ASC serves is that of providing an excellent Apple Customer Experience. Responsibilities include: * Promoting Apple products and solutions Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.