TweetFollow Us on Twitter

Dec 01 REALbasic

Volume Number: 17 (2001)
Issue Number: 12
Column Tag: Declaring External Functions

by Joe Strout

Declaring External Functions in REALbasic

Harness the power of toolbox calls without resorting to C

Declaring Your Intentions

REALbasic’s extensive library floats on top of the sea of low-level functions that comprise the operating system like a cruise ship, protecting you from the dangers that lurk below. This is a two-sided coin; it frees you to concentrate on what you want to accomplish, rather than the details of how it’s done on this or that platform, but it also places limits on what you can do. When you hit one of those limits, and need to accomplish something not directly supported by the REALbasic library, then you’re going to have to get wet.

But even then, you have a choice. You could write a plug-in in C++, and link this plug-in into your REALbasic application [reference - Erik’s article on plugin dev]. That gives you full power to do pretty much anything, but it also requires quite a bit of learning, especially for developers not already familiar with C++. The other option is to use the Declare statement, which makes a function in REALbasic that links to a function in the operating system or a shared library. This is done entirely within REALbasic; no C++ is involved. To extend the ocean analogy a just bit further: writing a plug-in is like diving into the ocean untethered, while using a Declare is like hanging onto a life preserver on a rope — there are still restrictions on what you can do, but it’s also a lot easier to avoid drowning.

Though the Declare statement is used entirely within REALbasic, it’s still an advanced feature and a source of difficulty for many experienced REALbasic coders. This article will attempt to clarify and illustrate its use. After reading this article, you’ll be able to declare calls to classic MacOS, Carbon, or Win32 system routines, as well as to other shared libraries. This gives you the power to do a wide range of things not otherwise possible in REALbasic.

The Declare Statement: A Close Look

With no further ado, let’s jump right into an example. Listing 1 shows a REALbasic function that toggles the “modified” flag of a window. (Under Mac OS X, this sets or clears the little dot in the red Close widget in the title bar.) Since the functions involved are only available in MacOS 8.5 and higher, it also checks the system version before attempting to call them.

Listing 1: ToggleModified

ToggleModified

Toggle the “Modified” flag of the given REALbasic window.  This subroutine requires MacOS 8.5 or higher,
and does nothing under older versions of MacOS.  It will not compile as-is for 68k (these functions are 
not available to 68k apps).

Sub ToggleModified(win As Window)
   // Toggle the given window’s Modified flag
   Dim sysVersion, err As Integer

   #if TargetCarbon
   Declare Function IsWindowModified Lib “CarbonLib” (window 
         as WindowPtr) as Boolean
   Declare Function SetWindowModified Lib “CarbonLib” (window 
         as WindowPtr, modified as Boolean) as Integer
   #else
   Declare Function IsWindowModified Lib “WindowsLib” (window 
         as WindowPtr) as Boolean
   Declare Function SetWindowModified Lib “WindowsLib” (window 
         as WindowPtr, modified as Boolean) as Integer
   #endif

   // check the system version, since these functions are only available
   // in MacOS 8.5 and higher
   if System.Gestalt(“sysv”, sysVersion) and sysVersion >= 
            &h0850 then
      // system version is OK, so do the toggle
      err = SetWindowModified(win, not IsWindowModified(win))
    end if
  end if
end Sub

There are several things to notice in this example. First, if we want to compile for both “classic” Macintosh and for Carbon, we need two versions of each Declare — one linking against CarbonLib, and the other against the appropriate toolbox library (often InterfaceLib, but WindowsLib in this case). Next, built-in REALbasic functions generally do the right thing for any version of MacOS your code may be running on, but it can’t do so with a Declare; it’s your responsibility to make sure that the function you’re calling will be available. In this case, that means checking that the system version is at least 8.5. But once you’ve done all this, using the function you’ve declared is easy — just call it like any ordinary REALbasic method.

Let’s look at the Declare statements more closely. First, note that the declaration occurs within some other REALbasic method (subroutine or function). Just like a local variable, these declarations are local to where they’re declared; they will not be visible outside of this method. There is currently no way to make such a declaration global, though you could make a global wrapper function (as we’ve essentially done in this example).

The declaration always begins with the keyword “Declare” followed by either “Function” or “Sub”; REALbasic doesn’t actually care which you use, but by convention you use “Sub” when the C return type is void. Next is the name of the function, exactly as it appears in the external library. This is also the name used to invoke the function, unless you specify an “Alias” clause (which we’ll cover a bit later).

The next part of the declaration is the library name. This is the fragment name as it appears to the Code Fragment Manager, not the file name as it appears in the Finder; and unlike most words in REALbasic, this name is case sensitive. Finding this name is not hard, but we’ll come back to it a bit later.

Next come the function parameters, and finally the return type. This is where things get interesting. The documentation or header files on which you’re basing your Declare probably specify the parameter and return types with C syntax, rather than REALbasic. It may say something like “char *” or “Str255” or something unpalatable. What to do?

The Right Type for the Job

Most of the work in creating a Declare statement is in finding the right conversions between the C types you see in the headers and documentation, and the REALbasic types that serve the same purpose. Fortunately you have this article, which contains the very handy Table 1. This shows you some of the most common C types, and the corresponding REALbasic types you should use in a Declare statement.

Table 1: C types and REALbasic
equivalents for Declare statements

C data type Declare type Variable Type
Boolean Boolean Boolean
long Integer, OSType, Color Integer, String, Color
int
UInt32
SInt32
void*
Ptr
(etc.)
OSType OSType (parameters only) String
ResType
DescType
short Short Integer
unsigned short
UInt16
SInt16
float Single Single
double Double Double
Str255 PString String
Str63
Str31
unsigned char *
char * CString (parameters only) String
WindowPtr WindowPtr Window
WindowRef (parameters only)
void* Ptr MemoryBlock
Ptr
(or pointer to data structure)

The first column of this table is the data type the function is expecting, as you might see it in the documentation or the C header file. The middle column shows the corresponding types you could use in the Declare statement. Finally, the last column shows the “natural” REALbasic types which most closely match the declared types; these are what you would pass (or get as a result) when calling the function.

REALbasic uses the type you specify in the Declare to figure out how much data to push onto the call stack when making the call; so the most important thing is to get the size right. If the function is expecting any 4-byte value, you can probably declare this as type Integer. If you declare it as Short instead, REALbasic (when compiling for 68k processors) will push only two bytes, the function will try to grab four, and you’ll almost certainly crash.

Many of the type choices are very straightforward; if the function wants a float, declare it as a Single and pass it a number. If the function is expecting a Pascal string, declare it as type PString, and when you invoke the function, give it any ordinary string. REALbasic will automatically convert its internal string representation into a Str255 when calling the function (but note: if the function expects a shorter string than that, it’s up to you to make sure your string isn’t too long before making the call). Or if the return type is a Pascal string, the returned value will be automatically converted into a normal REALbasic string.

With other types, it’s not so clear cut. Suppose the function expects a pointer. Should you declare this as type Integer, or type Ptr? The answer depends on the details. If it’s a function that allocates some data structure, returns you a pointer to it, and you simply pass it back to other functions without trying to peek at the data, then an Integer will do fine. REALbasic integers are four bytes, and a pointer is four bytes, so treating the pointer as if it were just a number will make life easiest for you. Most modern Apple toolbox calls, such as those in Carbon or QuickDraw 3D, are of this sort, since the underlying data structures are opaque.

If, however, the function is expecting you to allocate storage for some data before calling the function, then a bit more work is required. In this case, declare the parameter as type Ptr. Allocate the memory in the form of a REALbasic MemoryBlock, created with the NewMemoryBlock function (and be sure to make it the right size!). If the function is expecting the data structure to be initialized with some values, you can use the MemoryBlock methods to stuff appropriate values into it. Then, pass this MemoryBlock to the function. From the function’s point of view, it just gets a pointer to some already-allocated memory. It may stuff values into this area, which you can later read by using those MemoryBlock methods again.

Calling a Spade a Spade

Your Declare statement must name the shared library which implements the function. In the case of a Windows DLL, you simply use the file name. In the Mac world, we don’t rely on file names, which are too frequently changed to be reliable. So you must use the fragment name as seen by the Code Fragment Manager (CFM). Most of the MacOS toolbox is in the fragment “InterfaceLib” (or “CarbonLib” for Carbon/OS X apps). But suppose you’re calling some other library — for example, the “Quesa” high-level 3D graphics library. The CFM name of this library is “QuickDraw™ 3D” (because it’s a binary-compatible replacement for Apple’s QuickDraw 3D technology). If you don’t happen to have me around to tell you handy facts like this, how would you know?

If you have ResEdit handy, it can give you the answer. Drop the library onto ResEdit and open the “cfrg” (code fragment) resource. This gives you a list of code fragments — usually there’s only one — and the name you’re looking for is labeled “Member Name”. Copy that value, and paste it into your Declare statement as the library name.

You can also use PEF Viewer, a free little utility from Apple. It also lists the code fragments it finds, and even lets you peek into the code, data, and loader information for each. (The last can be handy when Carbonizing — if the shared library you’re using imports any symbols from anywhere other than CarbonLib, you probably can’t use it in a Carbon app.) The CFM name of the library is given right at the top, next to the disclosure triangle.

If you don’t have either of these tools handy, you can use REALbasic itself. Just launch REALbasic, and drag the shared library file into the project window. It will appear there with its CFM name, rather than its file name. If you’re curious, what you have there is the alternative interface to importing functions from shared libraries — useful if you need a large number of functions from a single shared library, and you want them to be global rather than local. Since you’re using Declares rather than importing the library, you can just make note of the name, then delete the library from your project.

TBFinder to the Rescue

Writing Declares has always been a bit of an arcane art. Even armed with the knowledge in this article, you’ll find yourself wondering if it’s really worth the trouble when you just need a quick Mac toolbox call. Fortunately, there is a tool which can take much of the guess-work out of writing a toolbox-related Declare.

TBFinder is an open-source REALbasic project coordinated by Fabian Lidman. First, you point it to your copy of Universal Headers — i.e., Apple’s toolbox interface files, which you can download from Apple’s Development Kits web site. Then you can just find the toolbox call you need by searching or browsing, and it writes the Declare statement for you. There are some caveats, but in many cases it’s as simple as that.

TBFinder’s search window — what you see when you launch the utility — is shown in Figure 1. If you don’t know the name of the call you’re looking for, click “Browse” to get a nice hierarchical list of the functions defined in all the interface files, then just double-click the one you want. If you do know the name of the function you need, type it in the edit field; if you happen to know the header in which it’s declared, you can check the “Look first in:” checkbox and choose the appropriate header from the pop-up menu. Then click Search.


Figure 1. TBFinder search window.

The result, assuming the function actually exists, is a window like that shown in Figure 2.


Figure 2. TBFinder result window.

TBFinder’s search window — what you see when you launch the utility — is shown in Figure 2. The key bit is the second section, where the REALbasic syntax is shown. You can either use the Copy command to move this text to the clipboard, or drag the little text-clipping icon directly into REALbasic. The other icons in the window are actually buttons that do things when you click on them: the upper left icon by the header file name reveals that header file in the Finder; the text file icon by the original C declaration opens the header file (careful — Apple’s headers are set to open in Macintosh Programmer’s Workshop); and the globe at upper right does a web search for the function name in Apple’s documentation.

At the bottom of the window, you’ll notice a handy note telling you whether or not the function appears to be Carbon-compatible. If it is, you can use it in a Carbon application by simply changing the library name to “CarbonLib”. In the case of a classic application, TBFinder correctly identifies the library for you, using a big internal look-up table which I fervently hope was generated automatically by parsing the various system libraries.

TBFinder also supports one other feature of the Declare that I not previously mentioned: the “Inline68K” block. Many Mac toolbox calls on 68k machines are not shared library calls at all, but rather direct jumps to system traps. The C headers give the necessary machine language glue with the xWORDINLINE macros; TBFinder converts this to RB syntax, and even appends the extra glue needed in some cases by RB itself. (Be sure to get the latest version of TBFinder; version 2.0, included on the REALbasic CD, does not do this correctly.)

Finally, note that while TBFinder is invaluable, it isn’t infallible. In particular, it takes its best guess at the appropriate parameter conversions, but these often require human judgment (see Table 1 again). Always double-check the parameter types TBFinder has chosen, and consider whether there are other choices that make more sense for you.

Some Examples

Now that we’ve covered all the basics, let’s look at some real examples. We already saw one in Listing 1, used to toggle the “modified” flag on a window. Listing 2 shows another example, a call to the toolbox routine ObscureCursor, which hides the cursor until the mouse is moved. As this routine takes no parameters and returns no result, the declaration is very straightforward.

Listing 2: ObscureCursor

ObscureCursor
Hide the cursor until the mouse is moved (MacOS only).

Sub ObscureCursor()
   {
  // Declare it with a “Sys” prefix to avoid a name clash
   #if TargetCarbon
  Declare Sub SysObscureCursor Lib “CarbonLib” Alias 
            “ObscureCursor” ()
  #else
  Declare Sub SysObscureCursor Lib “InterfaceLib” Alias 
            “ObscureCursor” () Inline68K(“A856”)
  #endif
  
  // Call it!
  SysObscureCursor
end Sub

Note that in this example, I’ve chosen to name the REALbasic subroutine exactly like the toolbox routine. That means that when I declare the toolbox call within the subroutine, I’d have a name clash unless I use the “Alias” option. “Alias” allows me to declare the system routine as SysObscureCursor, avoiding thus avoiding the clash, and allowing all other users of this subroutine to simply call “ObscureCursor”.

Naturally, if you needed to use HideCursor/ShowCursor to hide the mouse even when it moves — say, because you’re making a game and have a custom cursor or no need for a cursor at all — then the declarations would be very similar. But let’s suppose you need to hide the cursor only within a rectangular region of the screen, perhaps because you’re doing some animation there, or simply because you want to demonstrate a Declare involving a MemoryBlock. The toolbox call for this is ShieldCursor. TBFinder gives the declaration as:

Declare Sub ShieldCursor Lib “InterfaceLib” (shieldRect as Ptr, offsetPt as Point) Inline68K(“A855”)

Apple’s documentation gives the first parameter as a Rect pointer, which TBFinder has rendered as type Ptr. From Table 1, you know that a MemoryBlock is needed for times like this. We use the MemoryBlock to manually construct a Rect structure, recalling that a Rect is just a set of four short integers representing top, left, bottom, and right

Dim m As MemoryBlock

m = NewMemoryBlock(8) // 8 bytes (four 2-byte ints)
m.Short(0) = r.top
m.Short(2) = r.left
m.Short(4) = r.top + r.height
m.Short(6) = r.left + r.width

We can then pass this as the first parameter to ShieldCursor. What about the second parameter, “offsetPt”? Again referring to Apple’s documentation, we find that this is the offset from the global coordinate system. In other words, it’s the top-left corner of the window containing the rectangle to which we’re referring. TBFinder has left this declared as “Point”, which is not a valid Declare parameter type. But since a Point is the same size as an Integer, we can fairly easily construct an integer that contains the information we need:

Dim point As Integer

// put pt.v into the high word, pt.h into the low word:
point = BitwiseAnd(self.top * 65536, &HFFFF0000)
point = BitwiseOr(point, BitwiseAnd(self.left, &H0000FFFF))

Then, we simply change the Declare statement so that the second parameter is of type Integer, and we’re ready to go. The full listing for the ShieldCursor function is shown in Listing 3.

Listing 3: ShieldCursor

ShieldCursor
Hide the cursor within the given rectangle control.

Sub ShieldCursor(r As RectControl)
     Declare Sub SysShieldCursor Lib “InterfaceLib” Alias “ShieldCursor” (shieldRect as Ptr, offsetPt 
     as Integer) Inline68K(“A855”)
  
  Dim m As MemoryBlock
  Dim point As Integer
  
  // construct the rect within which the cursor will be shielded
  m = NewMemoryBlock(8)  // 8 bytes (four 2-byte ints)
  m.Short(0) = r.top
  m.Short(2) = r.left
  m.Short(4) = r.top + r.height
  m.Short(6) = r.left + r.width
  
  // construct the point that converts global to local coordinates
  point = -self.top * 65536 - self.left   
                           // pt.v in the high word, pt.h in the low word
  
  // make the call
  SysShieldCursor m,point
End Sub

Let’s end with a Windows declaration. I know, this is a Mac programming magazine, but sometimes you need to deploy your app for that Other Platform — and the ability to do so easily is one of REALbasic’s strengths. However, with the Declare statement, you’re making a direct call to a toolbox or shared library routine; this is rarely portable. So the first thing you’ll need to do, is conditionalize your code so that Mac declares are included only in Mac builds, and Windows declares are included only in Windows builds. You can use either “#if TargetMacOS” or “#if TargetWin32” for this purpose.

Next, you’ll need information on the Windows API. Two good references are given at the end of this article.

Finally, you’ll need to construct the Declare statement by hand. TBFinder can’t help you here; but with this article on your shelf, you’re well-equipped for the task. So let’s dive into an example.

Windows applications can take command-line parameters, and these are often used to specify options or initial conditions for the application. REALbasic can get these one at a time via the OpenDocument event, but in many cases it’d be preferable to get the whole command line. A search on the MSDN Online Library quickly leads to the GetCommandLine function, declared in the documentation as:

LPTSTR GetCommandLine(VOID);

This function takes no parameters, making our lives easy in that respect. And the return type, it turns out, is a C string of either ASCII or UniCode characters. This is an important point: many Windows functions come in both ASCII and UniCode versions, as signified under “Requirements” with a note such as “Unicode: Implemented as Unicode and ANSI versions on all platforms.” When you see this, it means that the function name given is not the real function name — you need to append “A” for the ASCII version, or “W” for the UniCode version. So the actual function name, for our purposes, is GetCommandLineA.

The return type in this case is an ordinary C string. But, while REALbasic knows how to automatically convert its String type into a CString for use as a parameter, it can’t do the opposite conversion. So we need another approach. A C string is really just a pointer to some data, so we can declare the return type as “Ptr”, and use a MemoryBlock to get at the data. The result is shown in Listing 4.

Listing 4: GetCommandLine

GetCommandLine
Get the full Win32 command line, including executable name and parameters.

Function GetCommandLine()
  #If TargetWin32
  Dim m as MemoryBlock
  Declare Function GetCommandLineA Lib “KERNEL32.DLL” () as Ptr
  m = GetCommandLineA()
  Return m.cstring(0)   // get the C string to which m points
  #Else
  return “Command line available on Win32 only.”
  #EndIf
End Function

There is one other trick that can sometimes make Windows declares easier. If you can find a web site or other documentation with Declare statements for Visual Basic — such as the last reference given at the end of this article — then you can use those Declare statements in REALbasic almost verbatim. You’ll just need to make a few changes: the “ByVal” keyword can be omitted, and data types may have to be translated according to Table 1 (e.g., use “Integer” where VB says “Long”).

Conclusion

REALbasic tries to abstract away the details of the underlying operating system, so you don’t have to worry about whether you’re running on classic MacOS, OS X, or some flavor of Windows. But sometimes you need more control. You may need to talk directly with the OS, or you may need access to some other shared library (such as OpenGL, for example). In those cases, the Declare statement is invaluable.

The Declare statement allows you to do most of the same things you could do directly in C. There are some limitations; you can’t call a function that requires a callback, and you can’t directly invoke a function pointer (e.g., to call a mach-o entry point loaded via the CFBundle API). For those, you’ll still need to write a plug-in. But for most other needs, you can Declare your external calls, providing a neater, more integrated solution.

While Declare gives you nearly the power of C, it gives you nearly the complexity of C as well. Writing a Declare statement is error-prone, and if done incorrectly, can crash your program (and under Classic MacOS, the system as well). Deciphering the headers and documentation for the calls you’re making requires some understanding of how things work in C or Pascal. But, with the tips gained here and a bit of study and experimentation, there will soon be little you can’t do in REALbasic.

References

REALbasic Home Page
http://www.realsoftware.com/realbasic

TBFinder Home Page
http://homepage.mac.com/fabianl/development/

Apple’s Developer Documentation
http://developer.apple.com/techpubs/

Apple’s Software Development Kits
http://developer.apple.com/sdk/

Microsoft’s Official SDK Documentation
http://msdn.microsoft.com/library/

Unofficial Windows API Guide
http://www.vbapi.com/ref/index.html


Joe Strout is a neuroscientist-turned-software engineer currently working for REAL Software, Inc. You can reach him at joe@strout.net.

 
AAPL
$526.19
Apple Inc.
+7.18
MSFT
$40.15
Microsoft Corpora
-0.26
GOOG
$541.40
Google Inc.
-15.14

MacTech Search:
Community Search:

Software Updates via MacUpdate

PDFpenPro 6.2 - Advanced PDF toolkit for...
PDFpenPro allows users to edit PDF's easily. Add text, images and signatures. Fill out PDF forms. Merge or split PDF documents. Reorder and delete pages. Even correct text and edit graphics! Create... Read more
PDFpen 6.2 - Edit and annotate PDFs with...
PDFpen allows users to easily edit PDF's. Add text, images and signatures. Fill out PDF forms. Merge or split PDF documents. Reorder and delete pages. Even correct text and edit graphics! Features... Read more
Monolingual 1.5.9 - Remove unwanted OS X...
Monolingual is a program for removing unnecesary language resources from OS X, in order to reclaim several hundred megabytes of disk space. It requires a 64-bit capable Intel-based Mac and at least... 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
Starcraft II: Wings of Liberty 1.1.1.180...
Download the patch by launching the Starcraft II game and downloading it through the Battle.net connection within the app. Starcraft II: Wings of Liberty is a strategy game played in real-time. You... Read more
Sibelius 7.5.0 - Music notation solution...
Sibelius is the world's best-selling music notation software for Mac. It is as intuitive to use as a pen, yet so powerful that it does most things in less than the blink of an eye. The demo includes... Read more
Typinator 5.9 - Speedy and reliable text...
Typinator turbo-charges your typing productivity. Type a little. Typinator does the rest. We've all faced projects that require repetitive typing tasks. With Typinator, you can store commonly used... Read more
MYStuff Pro 2.0.16 - Create inventories...
MYStuff Pro is the most flexible way to create detail-rich inventories for your home or small business. Add items to MYStuff by dragging and dropping existing information, uploading new images, or... Read more
TurboTax 2013.r17.002 - Manage your 2013...
TurboTax guides you through your tax return step by step, does all the calculations, and checks your return for errors and overlooked deductions. It lets you file your return electronically to get... Read more
TrailRunner 3.8.769 - Route planning for...
Note: While the software is classified as freeware, it is actually donationware. Please consider making a donation to help support development. TrailRunner is the perfect companion for runners,... Read more

Latest Forum Discussions

See All

Unpossible Review
Unpossible Review By Carter Dotson on April 17th, 2014 Our Rating: :: RALPH WIGGUM APPROVESUniversal App - Designed for iPhone and iPad Unpossible is much better than its English!   | Read more »
Hitman GO Review
Hitman GO Review By Carter Dotson on April 17th, 2014 Our Rating: :: GO HITMAN, GO!Universal App - Designed for iPhone and iPad Hitman GO is not the obvious way to do a mobile version of the Hitman series, but it’s an incredibly... | Read more »
Monster High Ghouls and Jewels is a Frea...
Monster High Ghouls and Jewels is a Freaky Fashion-Forward Match-3 Puzzler Posted by Rob Rich on April 17th, 2014 [ permalink ] | Read more »
Dinosaur Train A to Z Review
Dinosaur Train A to Z Review By Amy Solomon on April 17th, 2014 Our Rating: :: DINO DETAILSUniversal App - Designed for iPhone and iPad Dinosaur Train A to Z is an educational app about dinosaurs that includes In-App Purchases... | Read more »
Easter Comes to Junk Jack X – Bringing N...
Easter Comes to Junk Jack X – Bringing New Crafts, Chemistry, and More Posted by Rob Rich on April 17th, 2014 [ permalink ] Universal App - Designed for iPhone and iPad | Read more »
Call of Cookie Review
Call of Cookie Review By Jordan Minor on April 17th, 2014 Our Rating: :: COOKIE CRUMBLESUniversal App - Designed for iPhone and iPad Call of Cookie proves that plants aren’t the only fighting foods out there.   | Read more »
Corel Launches Video Editing App Pinnacl...
Corel Launches Video Editing App Pinnacle Studio for iPhone, Updates iPad Version for iOS 7 Posted by Tre Lawrence on April 17th, 2014 [ | Read more »
Bad Vamp Review
Bad Vamp Review By Jennifer Allen on April 17th, 2014 Our Rating: :: BASIC VAMPIRIC ADVENTURESUniversal App - Designed for iPhone and iPad Run or destroy the vampires in this simple, single-screen game that lacks real bite.   | Read more »
The Shadow Sun gets a New Update, Goes o...
The Shadow Sun gets a New Update, Goes on Sale for the First Time Since its Release Posted by Tre Lawrence on April 17th, 2014 [ permalink ] | Read more »
Bullet Pea Review
Bullet Pea Review By Jordan Minor on April 17th, 2014 Our Rating: :: PEA SHOOTERUniversal App - Designed for iPhone and iPad Bullet Pea’s “jumps only” gameplay is novel in theory, but has problems in practice.   | Read more »

Price Scanner via MacPrices.net

Hyundai Brings Apple CarPlay To The 2015 Sona...
Hyundai Motor America has announced it will bring Apple CarPlay functionality to the 2015 Sonata. CarPlay is pitched as a smarter, safer and easier way to use iPhone in the car and gives iPhone users... Read more
Updated iPads Coming Sooner Than We Had Thoug...
MacRumors, cites KGI securities analyst Ming Chi Kuo, well-respected as an Apple product prognisticator, saying that Apple will introduce an upgraded iPad Air and iPad mini in 2014/Q3, meaning the... Read more
Toshiba Unveils New High And Low End Laptop M...
Toshiba has announced new laptop models covering both the high-end and low-end of the notebook computer spectrum. Toshiba 4K Ultra HD Laptop Toshiba’s new Satellite P55t features one of the world’s... Read more
Save up to $270 with Apple refurbished 13-inc...
The Apple Store has Apple Certified Refurbished October 2013 13″ Retina MacBook Pros available starting at $1099, with models up to $270 off MSRP. Apple’s one-year warranty is standard, and shipping... Read more
Apple now offering refurbished iPad mini with...
The Apple Store has Certified Refurbished 2nd generation iPad minis with Retina Displays now available starting at $339. Apple’s one-year warranty is included with each model, and shipping is free.... Read more
Microsoft Blinks – Drops Microsoft Office 365...
Microsoft has dropped the annual subscription fee for Microsoft Office 365 Personal – which is needed in order to create and edit documents in Microsoft Office for iPad. However, Apple’s iOS and OS X... Read more
New AVG Vault Apps for iOS and Android Help K...
AVG Technologies N.V. an online security company for 177 million active users, has announced the launch of its latest mobile application, AVG Vault. The free app introduces an innovative user... Read more
Free Local Carrot iPhone App Helps Find Fresh...
I love fresh vegetables. I’m not a vegan, although I was for several years in the 1980s, but fresh vegetables and other whole foods are still my dietary mainstays as a matter of taste rather than... Read more
CarSO Pro – Car Service and Finance Manager/O...
Lviv, Ukraine-based BM-Studios’ CarSO Pro is a tool to manage operations concerning your car. Never forget to change the oil or prolong the insurance for your car. Remember when you’ve done the car... Read more
Apple refurbished iPad Airs available startin...
Apple is now offering Certified Refurbished iPad Airs for up to $140 off MSRP. Apple’s one-year warranty is included with each model, and shipping is free. The following Airs are available today: -... Read more

Jobs Board

*Apple* Solutions Consultant (ASC) - Apple (...
**Job Summary** The ASC is an Apple employee who serves as an Apple brand ambassador and influencer in a Reseller's store. The ASC's role is to grow Apple Read more
*Apple* Retail - Manager - Holyoke - Apple I...
Job Summary Keeping an Apple Store thriving requires a diverse set of leadership skills, and as a Manager, you’re a master of them all. In the store’s fast-paced, Read more
*Apple* Retail - Manager - Apple (United Sta...
Job SummaryKeeping an Apple Store thriving requires a diverse set of leadership skills, and as a Manager, you're a master of them all. In the store's fast-paced, dynamic Read more
*Apple* Solutions Consultant (ASC) - Apple (...
**Job Summary** The ASC is an Apple employee who serves as an Apple brand ambassador and influencer in a Reseller's store. The ASC's role is to grow Apple Read more
*Apple* Retail - Market Leader - Cincinnati...
…challenges of developing individuals, building teams, and affecting growth across Apple Stores. You demonstrate successful leadership ability - focusing on excellence Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.