27 July 2013

Beware of a pitfall when reading the OS X clipboard with the Carbon API

This is a heads-up for all those who read the Clipboard with the Carbon API (e.g. PasteboardCreate).

This is about rare but possible issue where you might be reading the clipboard contents incorrectly.

A very simple demo for this is the following:

  1. Open Automator to create a new Workflow.
  2. Add a Run Shell Script, with the command: ls -l /
  3. Add a Copy to Clipboard.
  4. Run it.

Launch TextEdit and Paste into a document. You should be seeing the listing of your root folder.
That's what is expected.

Now try your Carbon app and see what it takes from the same clipboard.
Does it only see one line of the clipboard ("total NNN")? Then you're subject to this issue.

Well, here's the explanation: That darn automator operation puts each line as a separate item into the pasteboard instead of putting all lines into a single text item. (The Finder does that, too, if you Copy a multi-selection of files.)

The fact that this Automator operation does it this way is suggesting that other NeXT (Cocoa) based apps may do the same, so you better be prepared for it.

To deal with this, you'll have to iterate over all items (whose count you find via PasteboardGetItemCount), and concatenate them with a line delimiter in between.
Or use NSPasteboard and get the NSStringPboardType, which contains all in one, with the proper delimiters.

Note: You can access the pasteboard using any of the 3 APIs (Scrap Mgr, Carbon Pastebaord, NSPasteboard) at the same time. E.g., if you put a new item into the Carbon Pasteboard, it becomes instantly available to the other APIs as well. Meaning that the 3 pasteboards are fully synchronized.

Therefore, you could just handle this special case like this, provided you're interested in text:

 if PasteboardGetItemCount() > 1 then
   txt = [[NSPasteboard pasteboardWithName:NSGeneralPboard] dataForType:NSStringPboardType]

No comments:

Post a Comment