TweetFollow Us on Twitter

MACINTOSH C CARBON
MACINTOSH C CARBON: A Hobbyist's Guide To Programming the Macintosh in C
Version 1.0
2001 K. J. Bricknell
Go to Contents Go to Program Listing

CHAPTER 20

CARBON SCRAP

The Carbon Scrap Manager and the Scrap

Introduction

The inclusion of the word "Carbon" in the title of this chapter is quite deliberate, reflecting the fact that, in Carbon, the original Scrap Manager has been redesigned to fully support the needs of the preemptively scheduled Mac OS X.

Applications which support cut, copy, and paste operations write data to, and read data from, the scrap. The scrap is a storage area, maintained by the Scrap Manager, which holds the last text, graphics, sounds, etc., cut or copied by the user.

The various data formats in which data may be written to, and read from, the scrap are called scrap flavours. A scrap flavour is a self-contained, self-describing stream of bytes which represent a discreet object such as a picture or text selection. Each scrap flavour has a scrap flavour type and a set of scrap flavour flags. The scrap may contain data in one or more flavours, each flavour being a different representation of the same object.

Your application specifies the scrap flavour, or flavours, to be read from, and written to, the scrap. The ultimate aim is to allow the user to copy and paste documents:

  • Within a document created by your application.

  • Between different documents created by your application.

  • Between documents created by your application and documents created by other applications.

Location of the Scrap

On Mac OS 8/9, space is allocated for the scrap in each application's heap. The system software stores a handle to the scrap of the current process in the system global variable ScrapHandle. When an application is launched, data is copied to the newly activated application's heap from the previously active application's heap. If the scrap is too large to fit in the application's heap, the scrap is copied to disk. In this event, the handle to the scrap is set to NULL to indicate that the scrap is on disk.

On Mac OS X, the scrap is held by the pasteboard server.

Scrap Reference

A scrap is referred to by a scrap reference. The data type ScrapRef is defined as a pointer to a scrap reference:

     typedef struct OpaqueScrapRef *ScrapRef;

Note that, although there is only one scrap, there may be multiple ScrapRef values. A ScrapRef value is valid only until the scrap is cleared.

Scrap Flavours

Standard Scrap Flavours

Your application should be capable of writing at least one of the following standard scrap flavours to the scrap and should be capable of reading both:

  • 'TEXT' (that is, a series of ASCII characters).

  • 'PICT' (a QuickDraw picture).

Optional Flavours

Your application may also choose to support the following optional scrap format types:

  • 'styl' (a series of bytes which have the same format as a TextEdit 'styl' resource, and which describe styled text data).

  • 'movv' (a series of bytes which define a movie, and which have the same format as a 'movv' resource).

Private Flavours

It is also possible for your application to use its own private flavour, or flavours, but this should be in addition to at least one of the standard flavours.

Preferred Flavour

Recall that each flavour in the scrap (assuming there is more than one) is simply a different representation of the same object.

Your application should have a preferred scrap flavour. When reading data from the scrap, your application should request its preferred flavour first and only request its next preferred flavour if the preferred flavour does not exist in the scrap. When writing data to the scrap, your application should write its preferred flavour first. Any additional flavours should be written in the preferred order.

Implementing Edit Menu Commands

You use the Edit menu Cut, Copy, and Paste commands to implement cutting, copying, and pasting of data within or between documents. The following are the actions your application should perform to support these three commands:

Edit Command

Actions Performed by Your Application

Cut

If there is a current selection range, copy the data in the selection range to the desk scrap and remove the data from the document.

Copy

If there is a current selection range, copy the data in the selection range to the desk scrap.

Paste

Read the desk scrap and insert the data (if any) at the insertion point, replacing any current selection.

The insertion point in a text document is represented by the blinking vertical bar known as the caret. There is a close relationship between the selection range and the insertion point in that the insertion point is, in effect, an empty selection range.

If your application implements a Clear command, it should remove the data in the current selection range but should not save the data to the desk scrap.

Cut and Copy - Putting Data in the Scrap

A typical approach to implementing the Cut and Copy commands is as follows:

  • Determine whether the frontmost window is a document window or a dialog.

  • If the frontmost window is a document window:

    • Call ClearCurrentScrap to purge the current contents of the scrap.

    • Call GetCurrentScrap to obtain a reference to the current scrap.

    • Determine whether the current selection contains text or a picture.

    • If the current selection is text, get a pointer to the selected text and get the size of the selection. If the current selection is a picture, get a pointer to the picture structure and get the size of that structure.

    • Call PutScrapFlavor to write the data to the scrap, passing the appropriate flavour type in the flavorType parameter.

    • If the command was the Cut command, delete the selection from the current document.
    
    

  • If the frontmost window is a dialog, use the Dialog Manager functions DialogCut or DialogCopy, as appropriate, to write the selected data to the scrap.

Paste - Getting Data From the Scrap

When you read the data from the scrap, your application should request the data in the application's preferred flavour type. If your application determines that that flavour does not exist in the scrap, it should then request the data in another flavour. If your application does not have a preferred flavour type, it should read each flavour type that your application supports.

If you request a scrap format that is not in the scrap, the Scrap Manager uses the Translation Manager to convert any one of the scrap flavour types currently in the scrap into the scrap flavour requested by your application. The Translation Manager looks for a translator that can perform one of these translations. If such a translator is available, the Translation Manager uses the translator to translate the data in the scrap into the requested flavour.

A typical approach to an implementation of the Paste command, for an application that prefers a flavour type of 'TEXT' as its first preference, is as follows:

  • Determine whether the frontmost window is a document window or a dialog.

  • If the frontmost window is a document window:

    • Call GetCurrentScrap to obtain a reference to the current scrap.

    • Call GetScrapFlavorFlags to determine whether the preferred flavour exists in the scrap.

    • If the preferred flavour type ('TEXT') does exist, call GetScrapFlavorSize to get the size of the text data, allocate a relocatable block of that size, and call GetScrapFlavorData to read the data into that block. Copy the data in the relocatable block to the current document at the insertion point.

    • If the preferred flavour type does not exist, call GetScrapFlavorFlags again to determine whether the next preferred flavour (say, 'PICT') exists in the scrap. If it does, call GetScrapFlavorSize to get the size of the picture data, allocate a relocatable block of that size, and call GetScrapFlavorData to read the data into that block. Call DrawPicture to draw the picture described by the data in the relocatable block in the current document at the insertion point.

  • If the frontmost window is a dialog, use the Dialog Manager function DialogPaste to paste the text from the scrap in the dialog.

Enabling the Paste Menu Item

Your application can determine whether to enable the Paste item in the Edit menu by calling GetScrapFlavorFlags to determine whether the scrap contains data of the flavour type specified in that call. GetScrapFlavorFlags returns noErr if the specified flavour exists.

Example

Fig 1 illustrates two cases, both of which deal with a user copying a picture consisting of text from a source document created by one application to a destination document created by another application.

In the first case, the source application has chosen to write only the 'PICT' flavour to the scrap, and the destination application has pasted the data, in that flavour, to its document.

In the second case, the source application has chosen to write both the 'TEXT' and 'PICT' flavours to the scrap, and the destination application has chosen the 'TEXT' flavour as the preferred flavour for the paste. The data is thus inserted into the document as editable text.

Clipboard Windows

Your application can provide a Show Clipboard command in the Edit menu which, when chosen, shows a window which displays the current contents of the scrap. Such a window is known as a Clipboard window. The Show Clipboard command should be toggled with a Hide Clipboard command to allow the user to hide the Clipboard window when required.

Although the scrap may contain multiple scrap flavours, your Clipboard window should ordinarily display the data in the application's preferred flavour only.

If the user has chosen to open the Clipboard window, your application should hide the window on receipt of a suspend event and show it when a resume event is received. This is necessary because the contents of the scrap could change while the application is in the background.

Transferring the Desk Scrap to Disk - Mac OS 8/9

Although, on Mac OS 8/9, the scrap is usually located in memory, your application can write the contents of the scrap in memory to a scrap file using UnloadScrap. You should do this only if memory is not large enough to hold the data you need to write to the scrap. After writing the contents of the scrap to disk, UnloadScrap releases the memory previously occupied by the scrap. Thereafter, any operations your application performs on data in the scrap affect the scrap as stored in the scrap file on disk. You can use LoadScrap to read the contents of the scrap file back into memory.

On Mac OS X, calls to LoadScrap and UnloadScrap are ignored.

Main Carbon Scrap Manager Functions

The main Carbon Scrap Manager functions are as follows:

Function

Description

GetCurrentScrap

Gets a reference to the current scrap. (Note that this reference will become invalid and unusable after the scrap is cleared.)

GetScrapFlavorFlags

Determines whether the scrap contains data for a particular flavour and provides information about that flavour if it exists. (Amongst other things, this function is useful for deciding whether to enable the Paste item in your Edit menu.)

GetScrapFlavorSize

Gets the size of the data of the specified flavour from the specified scrap.

GetScrapFlavorData

Gets the data of the specified flavour from the specified scrap.

ClearCurrentScrap

Clears the current scrap. This function should be called immediately the user requests a Copy or Cut operation.

PutScrapFlavor

Puts data on the scrap. Also promises data to the specified scrap (see below).

Associated Constants and Data Types

The following constants and data types are associated with the main Scrap Manager functions:

Scrap Flavour Type Constants

Constant

Flavour Type

Description

kScrapFlavorTypePicture 'PICT'

Picture

kScrapFlavorTypeText 'TEXT'

Text

kScrapFlavorTypeTextStyle 'styl'

Text style

kScrapFlavorTypeMovie 'moov'

Movie

Scrap Flavour Flag Constants

In the following, the first two constants may be passed in the flavorFlags parameter in calls to PutScrapFlavour, and the third is received in the flavorFlags parameter in calls to GetScrapFlavorFlags:

Constant

Meaning

kScrapFlavorMaskNone

No flags required.

kScrapFlavorMaskSenderOnly

Only the process which puts the flavour on the scrap can see it.

If another process puts a flavour with this flag on the scrap,your process will never see the flavour. Accordingly, there is no point in testing for this flag.

This flag is typically used to save a private flavour to the scrap so that other promised (see below) public flavours can be derived from it on demand.

kScrapFlavorMaskTranslated

The flavour was translated, by the Translation Manager, from some other flavour in the scrap. (Most callers should not care about this flag.) (Most callers should not care about this flag.)

ScrapFlavorInfo Data Type

The ScrapFlavorInfo data type describes a single flavour within a scrap and is used by those functions which get information about the current scrap (GetScrapFlavorFlags, GetScrapFlavorSize, and GetScrapFlavorData):
     struct ScrapFlavorInfo 
     {
       ScrapFlavorType  flavorType;
       ScrapFlavorFlags flavorFlags;
     };
     typedef struct ScrapFlavorInfo ScrapFlavorInfo;

Private Scrap

As an alternative to writing to and reading from the scrap whenever the user cuts, copies and pastes data, your application can choose to use its own private scrap. An application which uses a private scrap copies data to its private scrap when the user chooses the Cut or Copy command and pastes data from the private scrap when the user chooses the Paste command.

Additional Actions - Old Scrap Manager

In the old pre-Carbon Scrap Manager, an application which used a private scrap had to take the following additional actions whenever it received suspend and resume events:

  • Suspend Event. On receipt of a suspend event, the application had to copy data from the private scrap to the scrap.

  • Resume Event. On receipt of a resume event, the application had to first examine the convertClipboardFlag bit in the message field of the resume event structure to determine if the data in the scrap had changed since the previous suspend event. If the data in the scrap had changed, the application had to copy the data from the scrap to its private scrap. The application's menu adjustment function enabled the Paste item if the data copied to the private scrap was of the preferred, or other acceptable, type.

The process is illustrated at Fig 2.

Additional Actions - Carbon Scrap Manager

In the preemptively scheduled Mac OS X, this rather straightforward approach is no longer feasible. Consider the following scenario on Mac OS X:

  • Application B, which has a private scrap, is the frontmost application. The user clicks in a window belonging to application A to make application A the frontmost application. Application B receives a suspend event and begins to convert its private scrap.

  • While application B is still converting its private scrap, application A has become the frontmost application, and the user clicks in its menu bar. Application A, needing to decide whether to enable the Paste item in its Edit menu, looks at the scrap to determine what flavours it contains. Because application B has not finished converting its private scrap, and thus has not put anything onto the scrap, application A finds nothing it wants on the scrap and, accordingly, disables the Paste item.

The situation in which application A finds itself with regard to the Paste item is not acceptable in terms of human interface. The user cannot be expected to know that application B is still converting its scrap and that application As Paste item will be enabled in due course.

Making Promises

The Carbon Scrap Manager eliminates this problem using the concept of promised flavours. If, in the above example, application B calls PutScrapFlavor with NULL passed in the flavorData parameter whenever the user chooses Cut or Copy, a promise is made that data of the flavour specified in the flavorType parameter will later be placed on the scrap. On checking the scrap, application A will see the promise and can thus enable its Paste item in the expectation that the actual data will eventually appear in the scrap. The actual data can then be provided by application B through a subsequent call to PutScrapFlavor during the execution of a scrap promise keeper (callback) function. (Scrap promise keeper callback functions are called by the Carbon Scrap Manager as required to keep an earlier promise of a particular scrap flavour.)

In the first (promise-making) call to PutScrapFlavor, passing a non-zero size in the flavorSize parameter is optional; however, providing the size is advisable because callers of GetScrapFlavorSize will then be able to avoid blocking. If the size is provided, the subsequent call to PutScrapFlavor must provide the same amount of data as was promised. If the size is unknown at the time of the promise, your application should pass kScrapFlavorSizeUnknown in the flavorSize parameter.

Note that the promise-making PutScrapFlavor call cannot be made when your application receives a suspend event. This is because of the fundamental difference between the receipt of suspend events in Carbon applications as compared with Classic applications (see Chapter 2). Making the promise each time the user chooses Cut or Copy involves very little overhead, since only the promise, not the data, is being placed on the scrap.

Calling In Promises

In applications that use the Classic event model, your application should invariably call CallInScrapPromises on exit to cater for the possibility that it may have made promises that, after it quits, it cannot possibly honour. CallInScrapPromises forces all promises to be kept. On Mac OS X, this action is necessary even if your application has itself made no promises, the reason being that it is possible that, unbeknown to the application, promises could have been made on its behalf. For example, when you copy TEXT data (which has ASCII 13 for line endings) onto the scrap, the Carbon Scrap Manager promises other flavours which have different line endings and/or text encodings so that Cocoa applications can paste.

Calling CallInScrapPromises is not necessary in applications which use the Carbon event model model because the call will be made automatically in that case.

TextEdit, Dialogs, and Scrap

TextEdit and Scrap

TextEdit is a collection of functions and data structures which you can use to provide your application with basic text editing capabilities.

If your application uses TextEdit in its windows, be aware that TextEdit maintains its own private scrap. Accordingly:

  • PutScrap is not used and the special TextEdit functions TECut, TECopy, and TEToScrap are used in the processes of cutting text from the document and copying text to the TextEdit private scrap and to the desk scrap.

  • GetScrap is not used and the special TextEdit functions TEPaste, TEStylePaste, and TEFromScrap are used in the processes of pasting text from the TextEdit private scrap and copying text from the desk scrap to the TextEdit private scrap.

Chapter 21 describes TextEdit, including the TextEdit private scrap and the TextEdit scrap-related functions.

Dialogs and Scrap

Dialogs may contain edit text items, and the Dialog Manager uses TextEdit to perform the editing operations within those items.

You can use the Dialog Manager to handle most editing operations within dialogs. The Dialog Manager functions DialogCut, DialogCopy, and DialogPaste may be used to implement Cut, Copy and Paste commands within edit text items in dialogs. (See the demonstration program at Chapter 8.)

TextEdit's private scrap facilitates the copying and pasting of data between dialogs. However, your application itself must ensure that the user can copy and paste data between your application's dialogs and its document windows. If your application uses TextEdit for all editing operations within its document windows, this is easily achieved because TextEdit's TECut, TECopy, TEPaste, and TEStylePaste functions and the Dialog Manager's DialogCut, DialogCopy, and DialogPaste functions all use TextEdit's private scrap.

Main Carbon Scrap Manager Data Types and Functions

Constants

Scrap Flavour Types

kScrapFlavorTypePicture    = FOUR_CHAR_CODE('PICT')  // Picture
kScrapFlavorTypeText       = FOUR_CHAR_CODE('TEXT')  // Text
kScrapFlavorTypeTextStyle  = FOUR_CHAR_CODE('styl')  // Text style
kScrapFlavorTypeMovie      = FOUR_CHAR_CODE('moov')  // Movie
kScrapFlavorTypeSound      = FOUR_CHAR_CODE('snd ')  // Sound

Scrap Flavour Flags

kScrapFlavorMaskNone       = 0x00000000
kScrapFlavorMaskSenderOnly = 0x00000001
kScrapFlavorMaskTranslated = 0x00000002

Promising Flavours

kScrapFlavorSizeUnknown    = -1

Result Codes

internalScrapErr            = -4988
duplicateScrapFlavorErr     = -4989
badScrapRefErr              = -4990
processStateIncorrectErr    = -4991
scrapPromiseNotKeptErr      = -4992
noScrapPromiseKeeperErr     = -4993
nilScrapFlavorDataErr       = -4994
scrapFlavorFlagsMismatchErr = -4995
scrapFlavorSizeMismatchErr  = -4996
illegalScrapFlavorFlagsErr  = -4997
illegalScrapFlavorTypeErr   = -4998
illegalScrapFlavorSizeErr   = -4999
scrapFlavorNotFoundErr      = -102
needClearScrapErr           = -100

Data Types

typedef struct OpaqueScrapRef *ScrapRef;
typedef FourCharCode               ScrapFlavorType;
typedef UInt32                     ScrapFlavorFlags;

ScrapFlavorInfo

struct ScrapFlavorInfo 
{
 ScrapFlavorType  flavorType;
 ScrapFlavorFlags flavorFlags;
};
typedef struct ScrapFlavorInfo ScrapFlavorInfo;

Functions

Obtaining a Reference to the Current Scrap

OSStatus  GetCurrentScrap(ScrapRef *scrap);

Obtaining Information About a Specific Scrap Flavour

OSStatus  GetScrapFlavorFlags(ScrapRef scrap,ScrapFlavorType flavorType,
          ScrapFlavorFlags *flavorFlags);

Obtaining the Size of Data of a Specified Scrap Flavour

OSStatus  GetScrapFlavorSize(ScrapRef scrap,ScrapFlavorType flavorType,
          Size *byteCount);

Obtaining the Data of a Specified Scrap Flavour

OSStatus  GetScrapFlavorData(ScrapRef scrap,ScrapFlavorType flavorType,
          Size *byteCount,void *destination);

Writing Data to the Scrap and Clearing the Scrap

OSStatus  PutScrapFlavor(ScrapRef scrap,ScrapFlavorType flavorType,
          ScrapFlavorFlags  flavorFlags,Size flavorSize,const void *flavorData);
OSStatus  ClearCurrentScrap(void);

Scrap Promise Keeping

ScrapPromiseKeeperUPP  NewScrapPromiseKeeperUPP(ScrapPromiseKeeperProcPtr userRoutine);
void      DisposeScrapPromiseKeeperUPP(ScrapPromiseKeeperUPP userUPP);
OSStatus  SetScrapPromiseKeeper(ScrapRef scrap,ScrapPromiseKeeperUPP upp,
          const void *userData);
OSStatus  CallInScrapPromises(void);

Application-Defined (Callback) Function

OSStatus myScrapPromiseKeeperFunction(ScrapRef scrap,ScrapFlavorType flavorType,
         void *userData);

Transferring the Scrap Between Memory and Disk (Mac OS 8/9)

SInt32 UnloadScrap(void); // Does nothing when called on Mac OS X
SInt32 LoadScrap(void);   // Does nothing when called on Mac OS X

 

Community Search:
MacTech Search:

Software Updates via MacUpdate

Artlantis Studio 5.1.2.7 - 3D rendering...
Artlantis Studio is a unique and ideal tool for performing very high resolution rendering easily and in real time. The new FastRadiosity engine now lets you compute images in radiosity-even in... Read more
MacUpdate Desktop 6.0.5 - Search and ins...
MacUpdate Desktop 6 brings seamless 1-click installs and version updates to your Mac. With a free MacUpdate account and MacUpdate Desktop 6, Mac users can now install almost any Mac app on macupdate.... Read more
BitTorrent Sync 2.0.82 - Sync files secu...
BitTorrent Sync allows you to sync unlimited files between your own devices, or share a folder with friends and family to automatically sync anything. File transfers are encrypted. Your information... Read more
Google Drive 1.20 - File backup and shar...
Google Drive is a place where you can create, share, collaborate, and keep all of your stuff. Whether you're working with a friend on a joint research project, planning a wedding with your fiancé, or... Read more
Simon 4.0.3 - Monitor changes and crashe...
Simon monitors websites and alerts you of crashes and changes. Select pages to monitor, choose your alert options, and customize your settings. Simon does the rest. Keep a watchful eye on your... Read more
Vitamin-R 2.23 - Personal productivity t...
Vitamin-R creates the optimal conditions for your brain to work at its best by structuring your work into short bursts of distraction-free, highly focused activity alternating with opportunities for... Read more
iDefrag 5.0.0 - Disk defragmentation and...
iDefrag helps defragment and optimize your disk for improved performance. Features include: Supports HFS and HFS+ (Mac OS Extended). Supports case sensitive and journaled filesystems. Supports... Read more
PCalc 4.2 - Full-featured scientific cal...
PCalc is a full-featured, scriptable scientific calculator with support for hexadecimal, octal, and binary calculations, as well as an RPN mode, programmable functions, and an extensive set of unit... Read more
FileZilla 3.10.2 - Fast and reliable FTP...
FileZilla (ported from Windows) is a fast and reliable FTP client and server with lots of useful features and an intuitive interface. Version 3.10.2: Note: Now requires a 64-bit Intel processor.... Read more
The Hit List 1.1.11 - Advanced reminder...
The Hit List manages the daily chaos of your modern life. It's easy to learn - it's as easy as making lists. And it's powerful enough to let you plan, then forget, then act when the time is right.... Read more

Protect Yourself from an Onslaught of Ca...
Surprise Attack Games has announced a Cat-astrophic new physics puzzler called Fort Meow! In the game, a young girl named Nia finds her grandfather’s journal which triggers an all mighty feline attack! Why do the cats want the journal? Who knows,... | Read more »
GDC 2015 – Jelly Reef will be Game Oven’...
GDC 2015 – Jelly Reef will be Game Oven’s Last Hurrah, and it Seems like a Good Note to Go Out on Posted by Rob Rich on March 4th, 2015 [ permalink ] It’s sad knowing that Game Oven ( | Read more »
daWindci Deluxe Review
daWindci Deluxe Review By Campbell Bird on March 4th, 2015 Our Rating: :: BLUSTERY PUZZLESUniversal App - Designed for iPhone and iPad This updated puzzle game offers some creative gameplay and new mechanics, but still suffers from... | Read more »
Dungeon Hunter 5 Coming on March 12
Gameloft has excitedly announced that Dungeon Hunter 5 is on its way! Once again, you will adventure across the land of Valenthia exploring dungeons and fighting monsters. The game will have a new asynchronous multiplayer mode called Strongholds... | Read more »
GDC 2015 – The Sandbox 2 is Coming, and...
GDC 2015 – The Sandbox 2 is Coming, and Now it has Textures! | Read more »
Warner Bros. Interactive Announces Mort...
Mortal Kombat X, by Warner Bros. and NetherRealm Studios, will be a a free-to-play fighting/card-battle Mortal Kombat game. The game promises card collecting, multiplayer team combat, classic characters such as Scorpion, Sub-Zero and Raiden, and the... | Read more »
GDC 2015 – Piloteer is Whitaker Trebella...
GDC 2015 – Piloteer is Whitaker Trebella’s Latest Project, and it’s Definitely Something DIfferent Posted by Rob Rich on March 3rd, 2015 [ permalink ] You know | Read more »
PangoLand Review
PangoLand Review By Amy Solomon on March 3rd, 2015 Our Rating: :: COME VISIT PANGO AND FRIENDSUniversal App - Designed for iPhone and iPad PangoLand is an open-ended world full of familiar characters, bright colors and interactive... | Read more »
Knights of Pen & Paper is Leveling U...
With the roll of a die and a critical success, Paradox Interactive has announced Knights of Pen & Paper 2! You’ll be taking your place at the table once again in this sequel to Knights of Pen & Paper +1 Edition. The game will introduce the... | Read more »
GDC 2015 – Project Highrise is an Intere...
GDC 2015 – Project Highrise is an Interesting Idea from SomaSim Posted by Rob Rich on March 3rd, 2015 [ permalink ] You might know SomaSim best from their gold rush sim, 1849< | Read more »

Price Scanner via MacPrices.net

iPad: A More Positive Outlook – The ‘Book Mys...
It’s good to hear someone saying positive things about the iPad. I’ve been trying to bend my mind around how Apple’s tablet could have gone from zero to bestselling personal computing device on the... Read more
Mac Pros on sale for up to $279 off MSRP
Amazon has Mac Pros in stock and on sale for up to $279 off MSRP. Shipping is free: - 4-Core Mac Pro: $2725.87, $273 off MSRP (9%) - 6-Core Mac Pro: $3719.99, $279 off MSRP (7%) Read more
Sale! 13-inch Retina MacBook Pros for up to $...
B&H Photo has 13″ Retina MacBook Pros on sale for up to $205 off MSRP. Shipping is free, and B&H charges NY sales tax only: - 13″ 2.6GHz/128GB Retina MacBook Pro: $1219.99 save $80 - 13″ 2.... Read more
Another Tranche Of IBM MobileFirst For iOS Ap...
IBM has announced the next expansion phase for  its IBM MobileFirst for iOS portfolio, with a troika of new apps to address key priorities for the Banking and Financial Services, Airline and Retail... Read more
Sale! 15-inch Retina MacBook Pros for up to $...
B&H Photo has the new 2014 15″ Retina MacBook Pros on sale for up to $250 off MSRP for a limited time. Shipping is free, and B&H charges NY sales tax only: - 15″ 2.2GHz Retina MacBook Pro: $... Read more
WaterField Designs Introduces the Minimalist...
With Apple Pay gaining popularity, Android Pay coming in May 2015, and loyalty cards and receipts that can be accessed from smartphones, San Francisco’s WaterField Designs observes that it may be... Read more
Sale! 15-inch 2.2GHz Retina MacBook Pro for $...
 Best Buy has the 15″ 2.2GHz Retina MacBook Pro on sale for $1774.99 $1799.99, or $225 off MSRP. Choose free home shipping or free local store pickup (if available). Price valid for online orders... Read more
13-inch 2.5GHz MacBook Pro (refurbished) avai...
The Apple Store has Apple Certified Refurbished 13″ 2.5GHz MacBook Pros available for $170 off the cost of new models. Apple’s one-year warranty is standard, and shipping is free: - 13″ 2.5GHz... Read more
13-inch 2.5GHz MacBook Pro on sale for $100 o...
B&H Photo has the 13″ 2.5GHz MacBook Pro on sale for $999.99 including free shipping plus NY sales tax only. Their price is $100 off MSRP. Read more
27-inch 3.5GHz 5K iMac in stock today and on...
 B&H Photo has the 27″ 3.5GHz 5K iMac in stock today and on sale for $2299 including free shipping plus NY sales tax only. Their price is $200 off MSRP, and it’s the lowest price available for... Read more

Jobs Board

*Apple* Solutions Consultant - Retail Sales...
**Job Summary** As an Apple Solutions Consultant (ASC) you are the link between our customers and our products. Your role is to drive the Apple business in a retail Read more
Position Opening at *Apple* - Apple (United...
…Summary** As a Specialist, you help create the energy and excitement around Apple products, providing the right solutions and getting products into customers' hands. You Read more
Position Opening at *Apple* - Apple (United...
**Job Summary** The Apple Store is a retail environment like no other - uniquely focused on delivering amazing customer experiences. As an Expert, you introduce people Read more
*Apple* Solutions Consultant - Retail Sales...
**Job Summary** As an Apple Solutions Consultant (ASC) you are the link between our customers and our products. Your role is to drive the Apple business in a retail Read more
*Apple* Pay Automation Engineer - iOS System...
**Job Summary** At Apple , great ideas have a way of becoming great products, services, and customer experiences very quickly. Bring passion and dedication to your job Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.