TweetFollow Us on Twitter

Ultra-Groovy LString Class

Volume Number: 15 (1999)
Issue Number: 1
Column Tag: PowerPlant Workshop

The Ultra-Groovy LString Class

by John C. Daub, Austin, Texas, USA

An introduction to the PowerPlant-way of working with strings

Hello, World!

Most software developers have been working with strings since they wrote their first program - that's what "Hello World!" is all about. To facilitate working with strings many libraries of utility functions have been written. Some people have their home-brewed string libraries, while others utilize third party libraries or use the libraries provided in Standard C and C++. These solutions are well and good, but they do not always translate very effectively into the world of Mac OS. Many of these offerings, like the Standard C and C++ libraries, are written to work with C-style strings - a sequence of characters terminated by a null character. But due to the Mac OS Toolbox's Pascal heritage, strings on the Mac are Pascal-style strings - a sequence of characters preceeded by a length byte which stores the length of the string. Consequently, a string library designed to work with Pascal-style strings is more valuable to the Mac OS software developer. Enter PowerPlant's LString class.

LString is a C++ abstract base class for working with Pascal-style strings. It provides means for converting strings to numbers and numbers to strings; obtain strings from numerous sources (characters, other strings, resources); copy, append, and compare strings; find, insert, remove, and replace substrings; and does so in a manner that respects the boundaries of Pascal-style strings, takes advantage of the C++ language, makes your code easier to read and understand, and most of all is easy and logical to use. The inherited classes LStr255, TString, and LStringRef provide the concrete means for working with strings in a manner very familiar to Mac OS software developers, so the learning curve for LString is not a steep one. And although LString is a PowerPlant class it can be used independent of the rest of PowerPlant; feel free to use it in all of your Mac OS software development efforts.

If LString sounds good to you, then please read on. In this article I hope to provide you with a good overview of what LString provides, and illustrate how it will make your software development efforts easier. Along the way I'll also show you a few of the really cool and groovy power-user features of LString. But don't worry! Those power-user features are so easy to use that you'll be an LString-Warrior before you know it!

First, Some Background

Before I go any further, I want to make sure that we're on the same grounds of understanding just what a string is, and what the differences are between the various types of strings. If you already understand what the different types of strings are, feel free to skip ahead to the next section.

Simply put, a string is a sequence of characters. This sentence is an example of a string.

A C-style string is an array of characters (char*). The internal representation of the string has a null character ('\0') at the end, to signal the end of the string, so the amount of storage required for the string is one more than the number of characters in the string. Due to the use of the null terminator, there is theoretically no limit to the length of a C-style string, but you must scan the entire string to determine the length of the string (the C standard library function strlen() can be used to determine the length of the string). So the string "Hello, World!" contains thirteen characters, but at least fourteen bytes must be allocated to hold that string.

A Pascal-style string is also an array of characters (unsigned char*). Like a C-style string, a Pascal-style string also requires one more than the number of characters in the string for storage. However unlike a C-style string (and this is the defining and differentiating characteristic) there is no null terminator at the end of the string; instead, the first byte of the string is used to store a count of the number of characters in the string. You do not need to scan the entire length of the string to determine its length - you can merely examine the first byte (length byte) of the string. Also unlike a C-style string, a Pascal-style string does have a limit; this limit is determined by the number of bytes allocated in the unsigned char* array (e.g. unsigned char[256] would allow a string up to 255 characters). As a Pascal-style string "Hello, World!" still contains thirteen characters and also needs at least fourteen bytes for storage, but the internal representation of the string is different. Finally, when specifying a Pascal-style string constant, they are typically prefaced by a \p to tell the compiler to treat this string as a Pascal-style string (e.g. "\pHello, World!" would be the actual way to represent our example string as a Pascal-style string). Figure 1 illustrates how the internal storage of the "Hello, World!" string differs as a C-style string and a Pascal-style string.

Figure 1. String internal representations.

In Figure 1, each column represents a byte in the array (note we start at zero, like any array). The top row is the byte count, the middle row is the C-style string, and the bottom row is the Pascal-style string. Notice that both string styles require the same amount of storage (fourteen bytes). The C-style string places a null terminator in the last byte (although it looks like two separate characters \0 is just a special single character). When the string is read in, characters are read one by one until the null terminator is reached. If we wanted to find the length of the C-style string we would scan the string, starting from the beginning, counting each character as we go along until we reach the null terminator (this is what strlen does). The Pascal-style string places the length of the string in the first byte of the array (in this case the number thirteen, not "13" as a string or character). When the string is read, the first byte is checked for the length, and then exactly that many characters are read. If we wanted to find the length of the string, we check the first byte (string[0]).

Both styles of strings have their strengths and weaknesses. C-style strings can be of an arbitrary length whereas Pascal-style strings tend to have a more fixed size. C-style strings also have more overhead involved in determining the length of the string (a function call and walking the entire string), but you can find the length of a Pascal-style string with a simple check of the length byte.

On the Mac OS, most strings are Pascal-style strings (since the OS and toolbox were originally written in Pascal). To more easily represent and identify strings, and provide a simple means for defining strings of different lengths, MacTypes.h (formerly Types.h) typedefs some arrays of unsigned char's. The most popular version is a Str255, which is an array of 256 unsigned char's. There are others (Str63, Str32, Str15, StringPtr, ConstStr255Param - see MacTypes.h for a complete listing), and although Str255's are the most commonly used, the discussions in this article apply to any of these type(def)s. The Mac OS can also have raw text runs (e.g. 'TEXT' resources, TERec, etc.), and you can use C-style strings as well. The only time you are "forced" to use a Pascal-style string is when you interact with the Toolbox. If you wish to use C-style strings otherwise, you are very welcome to do so, especially if you are more familiar with the C Standard Library. Furthermore, the Toolbox provides some Pascal to-from C string conversion routines (c2pstr and p2cstr are in the Universal Header TextUtils.h ), and even provides C-glue routines that are glue routines to Toolbox functions that take C-style strings as arguments instead (look for the symbol CGLUESUPPORTED throughout the Universal Headers).

But as most Mac OS software development sooner or later requires you to interact with the Toolbox, most people find it easier to use Pascal-style strings all the time (also avoids the constant overhead of back and forth conversions). Due to this preference is why PowerPlant offers a great solution in LString. Let's now take a look at what exactly LString has to offer.

What's in There?

The LString class (and all of the classes and material I'll discuss here) can be found within the PowerPlant folder of the Metrowerks CodeWarrior Professional product. Specifically within the files LString.cp and LString.h. If you own CodeWarrior Professional, go ahead and open up those two files and look over them. I don't expect you to necessarily understand what's in there right now, but give them a look over so you can know what I'm talking about. You might also find it handy to refer to the sources as I refer to various parts of it so you can see how all of this fits together. For reference, I am writing this article using CodeWarrior Pro 4 and a version of LString that should be part of PowerPlant v1.9.3 (which will be released as public netborne update to Pro 4, and should be available by the time you read this article).


LString is an abstract base class for working with Pascal-style strings. It defines almost all of the functionality that one would need for working with Pascal-style strings. LString also works to take advantage of the C++ concept of overloading. First many of the methods are overloaded to work with many data types (all built-in data types, both signed and unsigned, including floating point types; C-style strings; Pascal-style strings; FourCharCode; a Handle to text; other LString objects). Second, many of the methods are also offered as operator overloads, were logical, to make it easier for you to utilize these methods in your code. For example, operator += is the same as the Append() method. LString also defines some public methods as static so that non-LString objects can take advantage of some commonly needed string manipulations like copying and appending.

LString is designed to be clean, efficient, and work within the boundaries of the Mac OS and the Pascal-style strings utilized therein. As noted earlier, MacTypes.h defines different types of Pascal-style strings, like a Str255 or a Str63. Due to this ability to vary in storage length, any time length of string and/or storage is relevant to the functionality, LString always requires this information be provided, but typically also provides a default towards a Str255 as this is the most commonly used type. Furthermore, since Mac OS Pascal-style strings have 255 characters as the upper limit for strings (hence the Str255), LString always enforces this upper boundary where appropriate. If utilized correctly, LString should alleviate fears and eliminate the problem of array boundary overflows.

Although PowerPlant is a Mac OS-only framework, it does try to do what it can to aid those that might be using PowerPlant in a non-Mac context such as porting your Mac OS-based application to Windows. Some LString methods are only available under Mac OS (due to their nature), and techniques are provided for development environments that might not fully understand Mac OS conventions. For example, the traditional way to obtain the length of the string is to directly check the length byte. But since not all development environments support this method of access (of course CodeWarrior does), the LString::Length() method is provided as a certain means of always obtaining the length of the string.

As an implementation note, there is only one data member in LString: mStringPtr. mStringPtr is a StringPtr which points to your Pascal-style string. Note that the actual storage for the string is not part of LString. Without this sort of design, neither TString nor LStringRef could exist (I'll discuss these classes later in the article). So does this mean that you always have to allocate your own storage for your string? Not at all, as this is the purpose of LStr255.


LStr255 inherits from LString. You can find the declaration of LStr255 in LString.h and definition in LString.cp. If the name of the class looks familiar to you, this is intended. The design of LStr255 is to replicate the functionality of a Str255, but with lots of extras. The great part is an LStr255 can be used almost anywhere a regular Str255 is used and in the same manner. Furthermore an LStr255 inherits all of the functionality of LString, plus it provides the actual storage for the string itself (the mString data member) so you do not have to.

Listing 1: Use of Str255

Obtain and concatenate two strings
To explain a convention used in all listings: any function call
preceeded by the unary scope resolution operator (::) specifies
this symbol is located in the global namespace - the same place
where the Toolbox symbols are located. These are Toolbox calls.
Feel free to look them up in Inside Macintosh on the Apple WWW
site for more information and detail.

    // Declare a string and initialize it
    Str255    theString = "\pHello, World!";

    // Append another string, obtained from a STR# resource
    Str255 appendString;
    ::GetIndString(appendString, 128, 1);

    // Ensure we don't overrun our boundaries
    SInt16    charsToCopy = appendString[0];
    Size theStringSize = sizeof(theString);

    if ((theString[0] + charsToCopy) > (theStringSize - 1)) {
        charsToCopy = theStringSize - 1 - theString[0];

    // Append the string
    ::BlockMoveData((Ptr)&appendString[1], theString +
                theString[0] + 1, charsToCopy);

    // Reset the length byte
    theString[0] += charsToCopy;

    // Draw the string

Listing 1 demonstrates a typical set of actions that one might perform on a string. All of that work and code just to concatenate two strings. Listing 2 shows the same code but written using LString. Don't worry if you do not understand everything that is going on in Listing 2 because I'll cover it all in coming sections.

Listing 2: Use of LStr255

Obtain and concatenate two strings

    // Declare a string and initialize it
    LStr255    theString( "\pHello World" );

    // Append another string, obtained from a STR# resource
    LStr255    appendString(128, 1);

    theString += appendString;

    // Draw the string

As you can see comparing Listing 2 to Listing 1, the same result is accomplished but Listing 2 contains a lot less code and is much easier to read. This just scratches the surface of what LString can do.

Two usage notes. First, when you are using LStr255 objects and viewing them in a debugger, you will actually see two instances of your string data within the LStr255 object. One of these will be from mStringPtr and the other from mString. Why do you see two strings and why are they always in sync? Why not just have one string? Remember that mStringPtr is just a pointer to your actual storage for your string, mString; rather, mStringPtr points to mString. This is how things are designed and it's all OK, don't worry about it. However if they are not in sync, you might want to investigate as this could be signaling a problem. Second, beginning with the next section and continuing for the remainder of the article, I will be using LStr255 objects in all code listings because LStr255 is the most commonly used type of LString. Do remember that what applies in those listings will generally apply to other LString derivatives as well, like TString and LStringRef.


TString is a templatized version of LString. It allows you to utilize the power and functionality of LString upon any Pascal-style string type (Str255, Str63, Str15, etc.). Use of the class is exactly like using LStr255, except that you instantiate your object through normal C++ template instantiation mechanisms. Listing 3 is a rewrite of Listing 1 using TString. Note as well its similarity to Listing 2.

Listing 3: Use of TString

Obtain and concatenate two strings

    // Declare a string and initialize it
    TString<Str63>        theString("\pHello World");

    // Append another string, obtained from a STR# resource
    TString<Str255>        appendString(128,1);

    theString += appendString;

    // Draw the string


LStringRef is a newcomer to the LString family (it was introduced in PowerPlant v1.9.1, post CodeWarrior Pro 3). LStringRef provides you with a means to obtain the functionality of LString and use it to manipulate a string that you do not have ownership of. Unlike LStr255 and TString, LStringRef does not contain storage for the string itself; mStringPtr points to a string allocated elsewhere. For example, this can be used to change a string that is part of some data structure. Listing 4 demonstrates the use of LStringRef to change the filename in an FSSpec from whatever it originally was to "Hello File! copy".

Listing 4: Use of LStringRef

    // Obtain our file spec
    FSSpec        theFileSpec;

    // Create the LStringRef and have it point to the filename
    LStringRef        fileName(sizeof(,

    // Change the filename entirely
    fileName = "Hello File!";

    // Actually it's a copy
    fileName += " copy";

Basic Features

Now that you've been introduced to the LString family and seen a little of what LString can do, it's now time to dig through the lines of code in LString.cp and LString.h to really see all that LString has to offer. By the way, do make sure you also read through LString.h as many of LString's functions are declared inline in the header file.

Object Construction

If you look through the LString sources, you'll notice that there is only one LString constructor. That's all that LString needs as it performs the core setup of the class's functionality. Where the constructors are really needed is within the subclasses. Look at the number of constructors there are for LStr255! And look what you can do with all of those constructors as well. You can create your LStr255 from: another LStr255, another LString, a Pascal-style string, a C-style string, an arbitrary string of text, a single character, data within a Handle, from a 'STR ' or 'STR#' resource, from a long or short integer, a FourCharCode, and from floating point values (long double). Wow! That covers just about every and any way you might want to create your LStr255 object.

If you look at the implementation of most of those LStr255 constructors, you'll see many of them call the Assign() method. Assign() assigns the given value to the LString object. Just as the constructors use Assign(), you are free to use Assign() as well when you wish to assign a value to your LString object. Furthermore, as a logical use of C++, you can see in LString.h that the assignment operator (operator =) has been overloaded with just as many combinations for those of you that prefer the use of operators in logical situations. Listing 5 demonstrates the many ways Assign() can be used.

Listing 5: The Many Faces of Assign()

Each line group produces the same result of creating an LStr255
object and giving it a string of "Hello, Assign!".

    // Create and assign by initialization
    LSt255        initString("Hello, Assign!");
    // Create and assign by Assign()
    LStr255    assignString;
    assignString.Assign("\pHello, Assign!");
    // Create and assign by assignment
    LStr255    assignmentString = assignString;

String Manipulation

Now that you have created your LString and given it some text, you will probably want to do something with the text in that string. This functionality is what LString tends to be used for most, and within this subset lies the use of Append().

Append() appends a given value to an LString object. What can be appended is again just about anything (see LString.h for a complete list). As with Assign() and operator =, so with Append() and operator +=. You'll probably find yourself using operator += a great deal as it's so simple to type and makes your code so much easier to read. One issue to note with operator += (and perhaps other overloaded functions in LString) is that depending what you are trying to append you may receive compiler errors about an ambiguous access to an overloaded function. For instance, the following line of code will generate this error because the compiler cannot determine if you intend 1 to be treated as char, unsigned char, long, or short:

    theString += 1;

If you receive this compiler error, all you need to do to resolve it is apply a static_cast (or C-style cast) which will tell the compiler explicitly how you wish the value to be treated:

    theString += static_cast<SInt32>(1);

In addition to member functions for appending, LString also provides some global string addition operators (operator +). They are not LString member operators, but do act upon LString objects. These operators concatenate LString objects with: another LString object, a pointer to a string, or a character. The result of the addition is an LStr255 object. You can find these operators declared about mid-way through LString.h and defined near the bottom of LString.cp.

Finally, what would string manipulation be if you could not compare strings! You will find in LString.h a boat-load of global comparison operators that let you do just about any sort of string comparison you can think of: equals (operator ==), not equals (operator !=), greater than (operator >), less than (operator <), greater than or equals (operator >=), and less than or equals (operator <=). Listing 6 demonstrates the many ways you can manipulate strings with LString.

Listing 6: String Manipulation

    // Create our string, "Hi"
    LStr255    theString("Hi");

    // Whoops! We forgot the punctuation
    theString += '!';

    // Create a new string from 2 smaller strings

    LStr255    newString;
    newString = theString + "\p My name is John.";

    // Is our newString the same as our old string?
    // If so, beep.
    if ( newString == theString ) {


Rounding out the basic features of LString are some utility functions. They fall into two groups: object-related and public.

The object-related utilities are utilities that are class member functions and only behave in relation to their associated LString object. These are methods like: Length(), which returns the string length as an UInt8; ShortLength() which returns length as an SInt16; LongLength() which returns length as an SInt32 (the different return types are to ease places where you need the string length but do not wish to typecast to match a function parameter or avoid an implicit arithmetic conversion); GetMaxLength(), to return the maximum length the string can be; TextPtr() and ConstTextPtr() to return a Ptr (or const Ptr) to the raw text (avoids those ugly (Ptr)&theString[1] situations, as was used in Listing 1); operator [] to allow access to individual characters in the string, just like you could with a basic array. Listing 7a illustrates the use of these utilities.

Listing 7a: Utilities

    LStr255    theLStr255("\pYea");
    TString<Str255>    theTStr255; // LString::LString() properly
                                         // initializes to null.

    // Manually copy the text out of the LStr255 into a Str255
    ::BlockMoveData(    theLStr255.ConstTextPtr(),
                                    theLStr255.LongLength()    );
    // Reset length byte
    theTStr255[0] = theLStr255.Length();

The public utilities of LString are a small group of static methods, publicly available for calling by pretty much anyone anywhere in your program (within reason, of course). These methods handle the most common string manipulations like: CopyPStr(), to copy one Pascal-style string into another Pascal-style string (e.g. Str255 to Str255); AppendPStr(), for a static version of LString::Append(); CStringLength() for obtaining the length of a C-style string with an upper limit of 255; FourCharCodeToPStr() and PStrToFourCharCode() for converting a FourCharCode (y'know, 'TEXT', 'PICT', 'PPob') to a Pascal-style string and back again; and FetchFloatFormat() and StringToLongDouble() to aid in some quick floating-point conversions. Listing 7b presents a display of these utilities' features.

Listing 7b: Static Utilities

    // Create a Pascal-style string and assign it a value
    Str255                herString;

    LString::CopyPStr("\pMary", herString);

    // Turn it into our app's signature
    FourCharCode    herSig;
    LString::PStrToFourCharCode(herString, herSig);

    // Clear original storage
    herString[0] = 0;

    // And back again
    LString::FourCharCodeToPStr(herSig, herString);

    // Add the rest
    LString::AppendPStr(herString, "\p Victoria");

Power Features

In addition to the basic functionality's discussed above, LString has some features for the power-user that help to round out the practicality of the class. If you consider yourself a beginner to LString, you should still give these power-features a look over as using these power-features is not difficult, and you can be a power-user in no time. The substring manipulations you may or may not use every day, but the "typecasting" abilities you'll find indispensable.

LString's ability to manipulate substrings provides you with the capability to perform substring searches, copies, and changes to that substring. In fact, you might even be able to create your own Find dialog using these features. The search functionality in LString allows you to: Find(), locate where a substring starts within the string; ReverseFind(), locate the position of a substring starting from the end of the string; to see if a string BeginsWith() or EndsWith() a specified string; find where the string starts within another string either from the beginning, FindWithin() or from the end, ReverseFindWithin(). In performing these searches, a comparison of text must of course be done. LString::ToolboxCompareText() is provided as the default mechanism for comparing the text; it uses the Toolbox CompareText() routine. If you do not wish to use the default comparison mechanism, you can specify your own CompareFunc via SetCompareFunc() to change it to whatever you would like. Of course after you have found your substring, you might want to do something with it. If you would like you can Insert() a string into your LString object, Remove() a substring from your object, or Replace() one substring with another. Or if you would just like to make a copy, operator () has been overloaded to provide you with an easy way to perform this copy. Listing 8 illustrates LString's substring manipulation features.

Listing 8: Substring Manipulation

    // Create the base string
    LStr255        theString("Get up. Stand up for your rights.");
    // Ensure the compare function is what we need
    // Find a target string
    StringPtr    targetString = "\pStand up";
    UInt8            targetLength = targetString[0];
    UInt8    index = theString.Find( (Ptr)&targetString[1],
                                     targetLength );
    // Make a copy of the target string
    LStr255        targetCopy(theString(index,targetLength));
    targetCopy += "\p. ";

    // Insert the copy into the base string
    theString += char_Space;
    theString.Insert( targetCopy, index );

What I think is one of the niftiest features of LString is, as I like to call them, the typecasting operators. These are a series of operator overloads that fake the appearance of a typecast to allow your LString object to be flexibly used in many situations. You can find the operators listed near the top of the LString declaration in LString.h. These operators include: StringPtr, ConstStringPtr, SInt32, double, long double, and FourCharCode. When one of these operators is applied to the LString object, it converts the string into the "requested type" and returns the conversion. That is, apply operator SInt32 and the string is converted to a long integer and that long integer returned. The way to apply these operators is just like a typecast, but it's not really a typecast; it's technically an application of that operator, but the implementation and application of that operator simulates a typecast for ease of use and improved code readability. Furthermore, when attempting to resolve types, the compiler can implicitly apply these operators to the LString object for you. Look back at Figure 2 and notice that we passed our LStr255 object directly to DrawString? Listing 9 should clarify how all of this works.

Listing 9: Typecasting Operators

    // Create our string (FIXEDDECIMAL comes from fp.h)
    LStr255    theString(3.14, FIXEDDECIMAL, 2);

    // Convert it and do some math (the static_cast technically
    // isn't necessary, but here for illustration. Note that it
    // looks like a typecast, but if you watch the code execute
    // you'll step into operator double().
    double number = static_cast<double>(theString);
    number *= 2;

    // Convert back to a string. Note there is no operator =
    // for floating point variables. This is because of the
    // need for extra information.
    theString.Assign(number, FIXEDDECIMAL,2);

    // Draw onscreen. Note the implicit operator call to
    // operator StringPtr.

PowerPlant uses this technique of typecasting operators throughout the framework as a handy way to allow your objects to be treated as more basic Toolbox types for increased flexibility and seemlessness between PowerPlant, the Toolbox, and your code. See the use of operator Handle and operator Ptr in UMemoryMgr classes for another set of examples. Also, if you have access to the Scott Meyers book More Effective C++, read Item 5: Be wary of user-defined conversion functions. Scott labels the above technique implicit type conversion operators and points out the various strengths and weaknesses of the above technique.

Is There A Downside?

As great as LString is, there are certainly a few downsides. There may be others, but these are the big ones in my book. First, if you don't like Pascal-style strings or perhaps they're not as useful as a C-style string would be in a given situation, then of course LString would fall under the same roof. But if you use and/or like Pascal-style strings then this isn't much of an issue. Second, this code is C++. If you need Pascal-style string helper functions in C or another language then LString will not be of much use to you. Third, LString's are C++ objects. As an object it will have some additional overhead and memory requirements, at least compared to plain arrays (e.g. LStr255 vs. Str255). Furthermore because LString's are objects you cannot place them inside TArray's, except, as with all objects and TArray, as pointers to the object allocated via new. Due to this extra work, it's probably easier to just store plain Str255's in a TArray instead. But do not fret! If you must use Str255's you can still gain the features and power of LString via the LStringRef class applied to your Str255's.

Give It A Try

If you haven't already, give LString a try. The code listings should all function as compilable snippets. And since LString is mostly independent of the rest of PowerPlant (you may need to add the PP_Constants.cp file to your project as well), you can easily drop LString.cp into a basic Toolbox or console stationery and give them a try. Step through each listing in the debugger (make sure inlining is set to "Don't inline") and watch how things work. Watch where you go, how that pertains to the section material being discussed, and how they all fit into the larger picture. Just play around and experiment.

I hope that I've been able to give you a good introduction to the LString class and it's family of subclasses and utilities. It provides the Mac OS software developer with a fairly simple yet powerful class for working with Pascal-style strings. With the ability to create strings from almost any source, manipulate the contents of that string, and convert it for use in just about any situation, LString is a tool worth having in your programmer's toolbox.

I hope you find LString to be as ultra-groovy as I find it to be. But just in case, I'll borrow one from Dennis Miller: "Of course that's just me. I could be wrong."


John C. Daub can't think of anything snazzy to put in his bio other than 311's a great band to listen to while writing articles. If you'd like to contact John, you can do so at


Community Search:
MacTech Search:

Software Updates via MacUpdate

iFFmpeg 6.2.5 - Convert multimedia files...
iFFmpeg is a comprehensive media tool to convert movie, audio and media files between formats. The FFmpeg command line instructions can be very hard to master/understand, so iFFmpeg does all the hard... Read more
DaisyDisk 4.4 - $9.99
DaisyDisk allows you to visualize your disk usage and free up disk space by quickly finding and deleting big unused files. The program scans your disk and displays its content as a sector diagram... Read more
BetterTouchTool 2.07 - Customize Multi-T...
BetterTouchTool adds many new, fully customizable gestures to the Magic Mouse, Multi-Touch MacBook trackpad, and Magic Trackpad. These gestures are customizable: Magic Mouse: Pinch in / out (zoom... Read more
BetterTouchTool 2.071 - Customize Multi-...
BetterTouchTool adds many new, fully customizable gestures to the Magic Mouse, Multi-Touch MacBook trackpad, and Magic Trackpad. These gestures are customizable: Magic Mouse: Pinch in / out (zoom... Read more
BetterTouchTool 2.07 - Customize Multi-T...
BetterTouchTool adds many new, fully customizable gestures to the Magic Mouse, Multi-Touch MacBook trackpad, and Magic Trackpad. These gestures are customizable: Magic Mouse: Pinch in / out (zoom... Read more
PDFpen 8.3.2 - $74.95
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
DiskCatalogMaker 6.5.20 - Catalog your d...
DiskCatalogMaker is a simple disk management tool which catalogs disks. Simple, light-weight, and fast Finder-like intuitive look and feel Super-fast search algorithm Can compress catalog data for... Read more
Things 2.8.9 - 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
PDFpenPro 8.3.2 - $124.95
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. Create fillable forms and tables of content... Read more
Things 2.8.9 - 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

Latest Forum Discussions

See All

Pokémon GO Generation 2 evolution guide
At long last, Niantic Labs finally unleashed the Generation 2 Pokémon into the wild. Pokémon GO trainers are scrambling to grab up this new set of 80 Pokémon. There are some special new tricks required to catch all of these new beasties, though.... | Read more »
The best new games we played this week
It feels as though the New Year got off to a creaking start as far as mobile games go, but that's changed over the past few weeks. The last few days alone have seen the debut of a number of wonderful games, so we thought we'd take the time to... | Read more »
Recruit more scallywags and discover new...
Get ready to show off your sea legs all over again in Oceans & Empires’ new grand update, which aims to make the act of rising to the role of seven seas ruler even more fresh and appealing, thanks to a richness of new content on both iOS and... | Read more »
Mage the Ascension: Refuge (Games)
Mage the Ascension: Refuge 1.0 Device: iOS Universal Category: Games Price: $4.99, Version: 1.0 (iTunes) Description: The groundbreaking roleplaying game Mage: The Ascension manifests in our turbulent present with Refuge, an... | Read more »
Vampire: Prelude (Games)
Vampire: Prelude 1.0 Device: iOS Universal Category: Games Price: $4.99, Version: 1.0 (iTunes) Description: The classic roleplaying game Vampire: The Masquerade returns to digital games with a Prelude of things to come. Experience a... | Read more »
Digby Forever Guide: How to dig to the d...
Digby Forever is a sparkling homage to arcade classics, and while you may be tiring of the number of arcade games being thrown at you, this endless digger finds many ways to stand out from the rest of the pack. The game manages to be challenging... | Read more »
The best sales on the App Store this wee...
It's been quite the week in mobile games, but if the latest releases(there were some pretty darn good ones, in case you missed out) aren't really doing the trick, perhaps some of these discounted games will. Many of these premium games had their... | Read more »
Why the new Fire Emblem Heroes update sh...
It’s exciting to see Nintendo delving into the mobile sphere, regardless of whether it’s to give fans another platform to enjoy their fans or simply a sound business venture. Two of the company's announced mobile games have finally come to... | Read more »
New Fire Emblem Heroes update adds new h...
Fire Emblem Heroes received a sizeable update first thing this morning. The update features a batch of fresh content along with a few updates to the game's systems. [Read more] | Read more »
The Deep Paths (Games)
The Deep Paths 1.0 Device: iOS iPhone Category: Games Price: $3.99, Version: 1.0 (iTunes) Description: 25% off launch sale!!! The Deep Paths: Labyrinth Of Andokost is a first-person, dungeon crawling RPG, with traditional grid-based... | Read more »

Price Scanner via

15-inch Touch Bar MacBook Pros on sale for up...
Amazon has 15″ Touch Bar MacBook Pros in stock today and on sale for up to $150 off MSRP including free shipping: - 15″ 2.7GHz Touch Bar MacBook Pro Space Gray: $2720.38 $79 off MSRP - 15″ 2.7GHz... Read more
Apple’s Education discount saves up to $300 o...
Purchase a new Mac or iPad using Apple’s Education Store and take up to $300 off MSRP. All teachers, students, and staff of any educational institution qualify for the discount. Shipping is free: -... Read more
13-inch 1.6GHz/256GB MacBook Air on sale for...
Newegg has the 13″ 1.6GHz/256GB MacBook Air (MMGG2LL/A) on sale for $1029.99 including free shipping. Their price is $170 off MSRP, and it’s the lowest price available for this model. Choose Newegg... Read more
Save up to $600 with Apple refurbished Mac Pr...
Apple has Certified Refurbished Mac Pros available for up to $600 off the cost of new models. An Apple one-year warranty is included with each Mac Pro, and shipping is free. The following... Read more
12-inch 1.1GHz Retina MacBooks on sale for $1...
B&H has 12″ 1.1GHz Retina MacBooks on sale for $150 off MSRP. Shipping is free, and B&H charges NY sales tax only: - 12″ 1.1GHz Space Gray Retina MacBook: $1149 $150 off MSRP - 12″ 1.1GHz... Read more
InTouch Health Expands iOS And Windows Produc...
Specialty telehealth enterprise provider InTouch Health has announced an expanded range of FDA Class I listed medical devices and software solutions for ambulatory, non-acute and non-emergent... Read more
iMobie Airs World’s 1st iCloud Manager with M...
iMobie Inc., an Apple-related software company, announced their newly-updated iPhone manager AnyTrans with exclusive feature to sync and manage contents across multiple iCloud accounts. With it,... Read more
New Proactive Apple Support Professional Cert...
Watchman Monitoring has announced Proactive Support Professional Certification at MacTech Pro. Watchman Monitoring is a premier Proactive Support Software as a Service (SaaS) tool for IT... Read more
13-inch 2.7GHz Retina MacBook Pro on sale for...
B&H Photo has the 2015 13″ 2.7GHz/128GB Retina Apple MacBook Pro on sale for $100 off MSRP. Shipping is free, and B&H charges NY tax only: - 13″ 2.7GHz/128GB Retina MacBook Pro (MF839LL/A): $... Read more
Back in stock: Apple refurbished 13-inch Reti...
Apple has Certified Refurbished 2015 13″ Retina MacBook Pros available for up to $360 off original MSRP, starting at $1099. An Apple one-year warranty is included with each model, and shipping is... Read more

Jobs Board

*Apple* Retail - Multiple Positions - Apple,...
Job Description: Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, Read more
Manager *Apple* Systems Administration - Pu...
Req ID 3315BR Position Title Manager, Apple Systems Administration Job Description The Manager of Apple Systems Administration oversees the administration and Read more
*Apple* Retail - Multiple Positions - Apple,...
SalesSpecialist - Retail Customer Service and SalesTransform Apple Store visitors into loyal Apple customers. When customers enter the store, you're also the Read more
*Apple* macOS Systems Integration Administra...
…most exceptional support available in the industry. SCI is seeking an Junior Apple macOS systems integration administrator that will be responsible for providing Read more
*Apple* Retail - Multiple Positions - Apple,...
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.