Archives / Search ›

ICeCoffEE and discontiguous selection on Tiger

Tonight I’ve been tackling the conflict between discontiguous selection in Tiger’s Cocoa text system and ICeCoffEE. I initially thought it would be a primarily technical problem to fix, but it turns out to be much more interesting.

For those of you who haven’t discovered it, discontiguous selection can be pretty useful. If you’re using Tiger, feel free to follow along, but if you’ve got ICeCoffEE installed, temporarily uncheck “⌘-click to open URLs and email addresses” in ICeCoffEE settings, under the Modules tab of the Application Enhancer System Preferences pane.

If you’re not using Tiger, open Nisus Writer Express or grab a demo of 2.1.3. Nisus has implemented discontiguous selection in its word processors for quite a while. (I seem to remember Microsoft Word 2004 does it, too, but I don’t have a copy to check.)

Open TextEdit (or Nisus Writer Express). Type a few words of nonsense, say “foo bar baz”. When you double-click “foo”, it selects the word, so you should see “foo bar baz” (in your preferred highlight color :). Now, hold down the Command (⌘) key, and double-click on “baz”. The selection should now be “foo bar baz”.

Nisus Writer Express (NWX) and Cocoa’s behaviors differ somewhat. Discontiguous selection in NWX is additive, whereas in Cocoa, it inverts. If you Command-double-click on “foo” again, NWX will leave “foo bar baz” selected, while TextEdit will show “foo bar baz”. I much prefer Cocoa’s selection inversion, as it allows you to undo one of a series of selection components without having to start over, and matches the established behavior of the Command modifier in lists.

So what does this all have to do with ICeCoffEE? With the introduction of discontiguous selections and their use of the Command key in text views, there is now a difference between a Command-click and a regular click, and a Command-drag and a regular drag within text, where before there was none.

With ICeCoffEE 1.4.1 enabled, the first click you make with the Command key held down tries to open a URL surrounding the place you clicked. What can I do to make ICeCoffEE work yet preserve the ability to select discontiguous regions? Let’s ignore the possibility that I could change ICeCoffEE’s invocation mechanism fundamentally—say, by adding Control to all the modifier combinations.

The easy case, where it’s obvious what to do—but ICeCoffEE 1.4.1 doesn’t—is when you drag the mouse with the Command key held down. Dragging means moving the mouse substantially, which I define as 4 pixels horizontally or vertically. Whether this drag serves to extend the selection or initiate a drag and drop operation is immaterial; ICeCoffEE should stay out of the way regardless.

If you’ve already got a discontiguous selection (or any selection at all), ICeCoffEE could also do nothing, allowing you to Command-double-click to your heart’s content. There are at least two problems with that, though:

  1. In a future version of ICeCoffEE, I plan to add support for opening a URL consisting of the selected text, if you Command-click somewhere within it. Currently, if you try that, ICeCoffEE does its usual thing of creating a selection starting where you clicked, and ignores the current selection. To change this behavior, then change back later, would be confusing.
  2. If the selected text is not visible, or the user just doesn’t notice, Command-clicking will cause nothing to apparently happen. I can see the bug reports now.

There’s even a case in which there is no selection and a Command-click should not trigger ICeCoffEE. When some users, such as my mother, use the Command key to perform discontiguous selection in lists, or select multiple icons with the Shift key in the Finder, they hold down the modifier key before selecting the first item or range. There is no difference between a modified and unmodified selection at that point, but with ICeCoffEE implementing the above behavior, the wrong thing would happen in the user’s eyes.

Another possibility: Always trigger on a Command-click which is not followed by a second click, incorporating a delay similar to the Finder’s file renaming delay. Try it: double-click on an icon’s name in the Finder. Did you click fast enough to open it, or did the name select itself for renaming? Conversely, try clicking once on the name, and note the time it takes for the rename field to appear. Would you mind that delay in ICeCoffEE for URL launching?

Or… can you think of a better way to distinguish between discontiguous selections and ICeCoffEE invocations?

The alpha version of ICeCoffEE I’ll release tomorrow employs a very simple test: if there’s any text selected, the Command-click is processed as a URL launch; if there isn’t, it gets passed through, and used for selection. This is not a good solution, as discussed above, but it’s working for now.

Assuming your eyes haven’t glazed over yet, your thoughts are appreciated.

NetNewsWire 2.0 released

NetNewsWire 2.0 is out. It’s been a long road—1.1d1 came out on August 26, 2003—but Brent and Sheila have created an exceptional, functional, elegant and high-quality product, and their relationship with their users is unparalleled. There are few other products I take hours of my time to write suggestions about, knowing they will be carefully considered and often implemented. Congratulations!

hex to string?

So I had a string I really needed to retrieve (a serial number that I appear to have misplaced, and which the software conveniently forgot when I swapped hard drives) which was stored in the app’s plist as a large ASCII-encoded hexadecimal number. Turning it into a string should have been easy, and I still maintain it is, but in my late-night torpor this is the best I could come up with:

In [41]: s = '30798C86...'

In [42]: l = [int(''.join(i), 16) for i in zip(s[::2], s[1::2])]
Out[42]: [48, 121, 140, 134, ...]

In [43]: struct.pack('B' * len(l), *l)
Out[43]: '0y\x8c\x86...'

at which point I realized that didn’t look anything like a serial number, so I’ll have to call my parents in the morning to see if they can find the box for said software (thanks, Apple). Still, there must be a better way to do this in Python without explicitly looping through the string.

Update: I asked on IRC, and got:

23:49  bdash> sabi: s.decode('hex') maybe?
23:49  sabi> !!!
23:49  sabi> yes, that's perfect
23:49  bdash> :-)

Thanks Mark.

PowerBook back, finally

I finally got my PowerBook back. I have been using my mother’s old PowerBook G4/400 for the past few months while it’s been away, and had upgraded to a 40 GB hard drive because I couldn’t live with the stock 10 GB one. The old PowerBook felt a lot subjectively faster starting up than the G4/800 I had been using, so when I got it back, I did a quick test.

PowerBook G4/400 with Samsung MP0402H drive (40 GB, 5400 RPM, 8 MB cache), from power on to my last startup item finishing under Mac OS X 10.3.9: 2 minutes. It would have been a few seconds faster if I had set the boot device properly in NVRAM.

PowerBook G4/800 with Toshiba MK4018GAS drive (40 GB, 4200 RPM, 2 MB cache), Mac OS X 10.3.8: 3 minutes, 40 seconds.

Aside from the differing hard drive speeds, the lack of fragmentation in the G4/400’s filesystem could have been a factor, too. I never realized that my drive only had 2 MB of cache; Apple putting that into their “high-end” PowerBook at the time was quite a cheap move. I’ll be swapping the Samsung drive into the G4/800 later today.

ICeCoffEE 1.4.2 status

I made some progress on ICeCoffEE 1.4.2 today—updated to handsome new versions of Unsanity Installer and APE, revised the readme, fixed some innocuous coding errors pointed out by Apple’s GCC 4.0 warnings, eliminated some undocumented API usage I can get rid of now 10.3.9 is the minimum supported OS, and got everything to build on Tiger with Xcode 2.0 (which I’m increasingly enjoying).

ICeCoffEE 1.4.1, in addition to breaking discontiguous selection in NSTextView, has no services-related functionality under Tiger. Nothing crashes; you just get no services menu or list of services to disable. I poked around a bit but seem to be only using the Cocoa services menu APIs in a documented (if slightly unorthodox) manner, so I’ll return to it tomorrow. HotService from DEVONtechnologies is a freeware input manager which adds a Services menu to the menu bar, which may be an interim solution for some ICeCoffEE users.

Also, I finally got another soap dish for the shower today, so we don’t have to accommodate two cakes of soap in a single dish that isn’t wide enough. It’s only been two years!

‹ Newer Posts  •  Older Posts ›