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 AÕs 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

Apple Pro Video Formats 2.0.1 - Updates...
Apple Pro Video Formats brings updates to Apple's professional-level codes for Final Cut Pro X, Motion 5, and Compressor 4. Version 2.0.1: Support for the following professional video codecs Apple... Read more
Maya 2015 - Professional 3D modeling and...
Maya is an award-winning software and powerful, integrated 3D modeling, animation, visual effects, and rendering solution. Because Maya is based on an open architecture, all your work can be scripted... Read more
EtreCheck 2.2 - For troubleshooting your...
EtreCheck is a simple little app to display the important details of your system configuration and allow you to copy that information to the Clipboard. It is meant to be used with Apple Support... Read more
OmniOutliner Pro 4.2 - Pro version of th...
OmniOutliner Pro is a flexible program for creating, collecting, and organizing information. Give your creativity a kick start by using an application that's actually designed to help you think. It's... Read more
VLC Media Player 2.2.1 - Popular multime...
VLC Media Player is a highly portable multimedia player for various audio and video formats (MPEG-1, MPEG-2, MPEG-4, DivX, MP3, OGG, ...) as well as DVDs, VCDs, and various streaming protocols. It... Read more
Nisus Writer Pro 2.1.1 - Multilingual wo...
Nisus Writer Pro is a powerful multilingual word processor, similar to its entry level products, but brings new features such as table of contents, indexing, bookmarks, widow and orphan control,... Read more
Tinderbox 6.2.0 - Store and organize you...
Tinderbox is a personal content management assistant. It stores your notes, ideas, and plans. It can help you organize and understand them. And Tinderbox helps you share ideas through Web journals... Read more
OmniOutliner 4.2 - Organize your ideas,...
OmniOutliner is a flexible program for creating, collecting, and organizing information. Give your creativity a kick start by using an application that's actually designed to help you think. It's... Read more
calibre 2.25.0 - Complete e-library mana...
Calibre is a complete e-book library manager. Organize your collection, convert your books to multiple formats, and sync with all of your devices. Let Calibre be your multi-tasking digital librarian... Read more
Things 2.5.4 - Elegant personal task man...
Things is a task management solution that helps to organize your tasks in an elegant and intuitive way. Things combines powerful features with simplicity through the use of tags and its intelligent... Read more

Lifeline... (Games)
Lifeline... 1.1 Device: iOS Universal Category: Games Price: $2.99, Version: 1.1 (iTunes) Description: Lifeline is a playable, branching story of survival against all odds. Using your iPhone, iPad, or Apple Watch, you will help... | Read more »
Pandemic: The Board Game Has Gone Univer...
Don't let the virus win! Now you can download Pandemic: The Board Game, by F2Z Digital Media, for all of your iOS devices. The app is based on the fantastic board game by Z-man games. As employees of the CDC, you and your friends will have to work... | Read more »
Get Ready to Read Bloomberg Business on...
Fans of Bloomberg Business will soon be able to get all their news on the Apple Watch. The app lets you get the top headlines on your main screen and bookmark stories to read later. Using the motion detection in the Apple Watch, the headlines are... | Read more »
Watch This Homerun is Batting for the Ap...
Eyes Wide Games' Watch This Homerun is purportedly the first sports game coming to the Apple Watch, where you'll be up to bat as the pitcher tries to out-manuever you with fastballs, curveballs, and changeups. Using one-touch controls you can try to... | Read more »
Field Trip Can Take You on a Guided Tour...
Field Trip, by Google’s Niantic Labs, is an exploration app that gives you details about the awesome places you can discover wherever you find yourself. The app can show you local history, delicious restraunts, the best places to shop, and places to... | Read more »
Watch Your Six - SPY_WATCH is Infiltrati...
SPY_WATCH, by Bossa Studios, is a new game designed for the Apple Watch. Runmor has it your spy agency has fallen out of favor. To save it, you'll need to train-up a spy and send them on missions to earn you a stunningly suspicious reputation and... | Read more »
Both Halo: Spartan Assault and Halo: Spa...
Halo: Spartan Assault and Halo: Spartan Strike, by Microsoft, have officially landed on the App Store. Spartan Assault pits you against the Covenant with missions geared to tell the story of the origin of Spartan Ops. In Spartan Strike you'll delve... | Read more »
The Apple Watch Could Revolutionize the...
It’s not here yet but there’s that developing sneaky feeling that the Apple Watch, despite its price tag and low battery life, might yet change quite a lot about how we conduct our lives. While I don’t think it’s going to be an overnight... | Read more »
Mad Skills Motocross 2 Version 2.0 is He...
Mad Skills Motocross 2 fans got some good news this week as Turborilla has given the game its biggest update yet. Now you'll have access to Versus mode where you can compete against your friends in timed challenges. Turborilla has implemented a... | Read more »
Kids Can Practice Healthy Living With Gr...
Bobaka is releasing a new interactive book called Green Riding Hood  in May. The app teaches kids about yoga and organic style of life through mini-games and a fun take on the classic Little Red Riding Hood fairy tale. | Read more »

Price Scanner via MacPrices.net

Sale! 15-inch Retina MacBook Pros for up to $...
 MacMall has 15″ Retina MacBook Pros on sale for up to $255 off MSRP. Shipping is free: - 15″ 2.2GHz Retina MacBook Pro: $1794.99 save $205 - 15″ 2.5GHz Retina MacBook Pro: $2244.99 save $255 Adorama... Read more
New 2015 MacBook Airs on sale for up to $75 o...
Save up to $75 on the purchase of a new 2015 13″ or 11″ 1.6GHz MacBook Air at the following resellers. Shipping is free with each model: 11" 128GB MSRP $899 11" 256GB... Read more
Clearance 13-inch Retina MacBook Pros availab...
B&H Photo has leftover 2014 13″ Retina MacBook Pros on sale for up to $250 off original MSRP. Shipping is free, and B&H charges NY sales tax only: - 13″ 2.6GHz/128GB Retina MacBook Pro: $1129... Read more
Clearance 2014 MacBook Airs available startin...
B&H Photo has clearance 2014 MacBook Airs available for up to $200 off original MSRP. Shipping is free, and B&H charges NY sales tax only: - 11″ 128GB MacBook Air: $729 $170 off original MSRP... Read more
16GB iPad mini 3 on sale for $349, save $50
B&H Photo has the 16GB iPad mini 3 WiFi on sale for $349 including free shipping plus NY sales tax only. Their price is $50 off MSRP, and it’s the lowest price available for this model. Read more
Mac minis on sale for up to $75 off, starting...
MacMall has Mac minis on sale for up to $75 off MSRP including free shipping. Their prices are the lowest available for these models from any reseller: - 1.4GHz Mac mini: $459.99 $40 off - 2.6GHz Mac... Read more
Taichi Temple First Tai Chi Motion Sensor App...
Zhen Wu LLC has announced the official launch of Taichi Temple 1.0, the first motion sensor app for Tai Chi, offering a revolutionary new way to de-compress, relax and exercise all at the same time.... Read more
CleanExit – Erase your Hard Drive Quickly, Se...
CleanExit works on both Macs and PCs, securely and permanently deleting all files from any type of hard drive, flash-based drive or camera media card making the files permanently unrecoverable.... Read more
250 iPhone 6 Tips eBook Released for $1.99
Bournemouth, UK based iOS Guides has released 250 iPhone 6 Tips, a new eBook available in the iBookstore that reveals a wealth of tips and tutorials for iPhone 6 and iPhone 6 Plus. Priced at $1.99,... Read more
TigerText Introduces First Secure Enterprise...
TigerText, a provider of secure, real-time messaging for the enterprise, has announced the launch of TigerText for the Apple Watch. TigerText for the Apple Watch enables users to securely send and... 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
*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
DevOps Software Engineer - *Apple* Pay, iOS...
**Job Summary** Imagine what you could do here. At Apple , great ideas have a way of becoming great products, services, and customer experiences very quickly. Bring Read more
*Apple* Pay - Site Reliability Engineer - Ap...
**Job Summary** Imagine what you could do here. At Apple , great ideas have a way of becoming great products, services, and customer experiences very quickly. Bring Read more
Sr. Technical Services Consultant, *Apple*...
**Job Summary** Apple Professional Services (APS) has an opening for a senior technical position that contributes to Apple 's efforts for strategic and transactional Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.