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

Macs Fan Control 1.4.4.0 - Monitor and c...
Macs Fan Control allows you to monitor and control almost any aspect of your computer's fans, with support for controlling fan speed, temperature sensors pane, menu-bar icon, and autostart with... Read more
calibre 2.69.0 - Complete e-book library...
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
Evernote 6.9.1 - Create searchable notes...
Evernote allows you to easily capture information in any environment using whatever device or platform you find most convenient, and makes this information accessible and searchable at anytime, from... Read more
jAlbum Pro 13.5 - Organize your digital...
jAlbum Pro has all the features you love in jAlbum, but comes with a commercial license. You can create gorgeous custom photo galleries for the Web without writing a line of code! Beginner-friendly... Read more
jAlbum 13.5 - Create custom photo galler...
With jAlbum, you can create gorgeous custom photo galleries for the Web without writing a line of code! Beginner-friendly, with pro results - Simply drag and drop photos into groups, choose a design... Read more
Google Chrome 53.0.2785.143 - Modern and...
Google Chrome is a Web browser by Google, created to be a modern platform for Web pages and applications. It utilizes very fast loading of Web pages and has a V8 engine, which is a custom built... Read more
Chromium 53.0.2785.143 - 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. Version 53.0.2785.143: [Security Fix] High CVE-2016-... Read more
QuickBooks 2015 16.1.7.1524 R8 - Financi...
Save 20% on QuickBooks Pro for Mac today through this special discount link QuickBooks 2015 helps you manage your business easily and efficiently. Organize your finances all in one place, track... Read more
Sierra Cache Cleaner 11.0.1 - Clear cach...
Sierra Cache Cleaner is an award-winning general purpose tool for macOS X. SCC makes system maintenance simple with an easy point-and-click interface to many macOS X functions. Novice and expert... Read more
Default Folder X 5.0.7 - Enhances Open a...
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 on... Read more

3 tips to aid your journey in Banner Sag...
Stoic Games brings us another viking epic in the guise of Banner Saga 2 this week. It’s a sweeping tale, richly animated and draped in melancholy and moments of beauty. The game’s been received as a much improved follow up to the first entry in the... | Read more »
Pumped BMX 3: Beginner tips and tricks
There’s a whole lot more to Pumped BMX 3 than meets the eye. Your goal is to perform a wide array of sweet flips and tricks, but that’s easier said than done. It takes well practiced timing and coordination, and the game doesn’t really explain that... | Read more »
Cybird’s latest release - BFB Champions...
Launched in the UK in early September, BFB Champions’ newest update is loaded with great new features, and looks set to outshine the original version by taking it out of soft launch and giving it a new lease of life. | Read more »
3 apps to boost your focus
As someone who works from home, my workspace is a minefield of distraction. Cats, tasty snacks, the wind blowing past my window, that cleaning that I suddenly can’t put off any longer. If I let distraction takes its course, I find that soon half... | Read more »
Pumped BMX 3 (Games)
Pumped BMX 3 1.0 Device: iOS Universal Category: Games Price: $3.99, Version: 1.0 (iTunes) Description: The final instalment of the smash hit #1 rated BMX game is here! Following on from the insane success of Pumped BMX 2, Pumped 3... | Read more »
4 games like Burly Men at Sea to inspire...
Burly Men at Sea is out today and it looks a treat. It tells the tale of three Scandinavian fishermen who leave the humdrum of their daily lives to go exploring. It’s a beautiful folksy story that unfurls as you interact with the environment... | Read more »
3 reasons you need to play Kingdom: New...
Developed by a tag team of indie developers - Thomas "Noio" van den Berg and Marco "Licorice" Bancale - Kingdom is a vibrant medieval fantasy adventure that casts players as a king or queen who must expand their empire by exploring the vasts lands... | Read more »
JoyCity have launched a brand new King o...
Great news for all of you Game of Dice fans out there - JoyCity have just released a brand new limited edition pack with a really cool twist. The premise of Game of Dice is fairly straightforward, asking you to roll dice to navigate your way around... | Read more »
Burly Men at Sea (Games)
Burly Men at Sea 1.0 Device: iOS Universal Category: Games Price: $4.99, Version: 1.0 (iTunes) Description: Burly Men at Sea is a folktale about a trio of large, bearded fishermen who step away from the ordinary to seek adventure. | Read more »
3 tips for catching the gnarliest waves...
Like a wave breaking on the shore, Tidal Rider swept its way onto the App Store charts this week settling firmly in the top 10. It’s a one-touch high score-chaser in which you pull surfing stunts while dodging seagulls and collecting coins. The... | Read more »

Price Scanner via MacPrices.net

CAZE Annouces New Zero 5 Case for Jet Black i...
Hong Kong basd CAZE has announced Zero 5 case for iPhone 7/ 7 Plus, one of the world’s thinnest clear hard cases, measuring just 0.5 millimeters. CAZE has been producing and improving the Zero 5... Read more
Nest Egg Inventory App for iOS Offers Conven...
Campbell, California based Winprogger LLC has announced the release and immediate availability of Nest Egg – Inventory 4.1.22, an important update to their easy-to-use, yet comprehensive inventory... Read more
Factor4, LLC Launches Apple iOS and Android G...
Factor4, LLC, which offers gift and loyalty services to the SMB marketplace, has released free mobile applications that enable merchants to process via all Apple and Android devices. The Apple and... Read more
15-inch Retina MacBook Pros on sale for $200...
B&H Photo has 15″ Retina Apple MacBook Pros on sale for $200 off MSRP. Shipping is free, and B&H charges NY tax only: - 15″ 2.2GHz Retina MacBook Pro: $1799 $200 off MSRP - 15″ 2.5GHz Retina... Read more
Apple refurbished iMacs available for up to $...
Apple has Certified Refurbished 2015 21″ & 27″ iMacs available for up to $350 off MSRP. Apple’s one-year warranty is standard, and shipping is free. The following models are available: - 21″ 3.... Read more
Check Apple prices on any device with the iTr...
MacPrices is proud to offer readers a free iOS app (iPhones, iPads, & iPod touch) and Android app (Google Play and Amazon App Store) called iTracx, which allows you to glance at today’s lowest... Read more
Apple price trackers, updated continuously
Scan our Apple Price Trackers for the latest information on sales, bundles, and availability on systems from Apple’s authorized internet/catalog resellers. We update the trackers continuously: - 15″... Read more
Apple refurbished 2016 13-inch MacBook Airs a...
Apple has Certified Refurbished 2016 13″ MacBook Airs available starting at $849. An Apple one-year warranty is included with each MacBook, and shipping is free: - 2016 13″ 1.6GHz/8GB/128GB MacBook... Read more
1.4GHz Mac mini on sale for $449, save $50
Adorama has the 1.4GHz Mac mini on sale for $50 off MSRP including free shipping plus NY & NJ sales tax only: - 1.4GHz Mac mini (Apple sku# MGEM2LL/A): $449 $50 off MSRP To purchase a mini at... Read more
Apple refurbished 2015 13-inch MacBook Airs a...
Apple has Certified Refurbished 2015 13″ MacBook Airs available starting at $759. An Apple one-year warranty is included with each MacBook, and shipping is free: - 2015 13″ 1.6GHz/4GB/128GB MacBook... Read more

Jobs Board

Systems Architecture Prototyping - *Apple*...
Changing the world is all in a day's work at Apple . If you love innovation, here's your chance to make a career of it. You'll work hard. But the job comes with more Read more
*Apple* Retail - Multiple Positions- Akron,...
Job Description:SalesSpecialist - Retail Customer Service and SalesTransform Apple Store visitors into loyal Apple customers. When customers enter the store, Read more
Hardware Design Validation Engineer - *Apple...
Changing the world is all in a day's work at Apple . If you love innovation, here's your chance to make a career of it. You'll work hard. But the job comes with more Read more
Systems Architecture Prototyping - *Apple*...
Changing the world is all in a day's work at Apple . If you love innovation, here's your chance to make a career of it. You'll work hard. But the job comes with more Read more
*Apple* Retail - Multiple Positions- South B...
Job Description: Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.