Ubuntu 6.06 and DPMS

It wasn't until I connected an Apple Cinema Display to my Ubuntu box that I realized that it wasn't the cheap Samsung display's fault it wasn't going to sleep. I had assumed that the Samsung's DPMS support was somehow lacking, because I couldn't believe that DPMS didn't just work out of the box. I couldn't believe that Ubuntu really thought that a jerky fade-to-black that leaves the display on, glowing that dull gray that is what passes for black on an LCD was sensible default behavior.

Turns out I was doing the Samsung an injustice. When the Apple display also failed to go to sleep, I realized it had to be Ubuntu's fault. A quick xset(1) later, and my display when to sleep when the computer had been idle for the time I specified. I went to bed a happy man, thinking I'd edit xorg.conf in the morning and add Option "StandbyTime" "10" (the server and xset(1) use different units; the server measures time in minutes).

In the morning, though, the display's back on. Weird. I read my mail and then, while I got ready for work, the display turned off again. So I go to work, and come back in the evening to find the display's back on. Weird.

I never did find out what turns the display on, but something sure does. Google only seemed to have advice about turning DPMS permanently off.

I decided it served me right for trying to mess around at a low level, and tried to work out how to tell the GUI what I wanted.

The configuration side of things is one of Ubuntu's weakest points. It's an utter dog's dinner. Would sir like "Preferences" or "Administration"? Sir doesn't know? Now, now, sir; are you sure you want to be touching any of these levers? You're clearly not trained for it. Yes, sir, I'm certain Windows and Mac OS don't consider the distinction between preferences and administration necessary, but what would sir expect from the likes of those two? Anyway, isn't sir forgetting the additional choices offered by the "Applications" menu, both "Add/Remove..." (no, I won't tell you what) and the "System Tools" submenu.

It's funny that Mac OS actually has nearly as many icons in its "System Preferences". You don't notice because some thought has gone into their arrangement. Only a few are gratingly arbitrary ("QuickTime" being under "Internet & Network", for example). And navigating around "System Preferences" is a lot less painful that GNOME's odd screen menu bar arrangement; it costs a lot less to choose the wrong panel because there's a handy "back" button.

But back to getting DPMS working on Ubuntu.

Some experimentation (and much cursing) later, I found that between them, "System" > "Preferences" > "Screensaver" and "System" > "Preferences" > "Power Management" both have a hand in making things work. I had to uncheck "Activate screensaver when session is idle" in the screensaver preferences, and move the "Set session as idle after" slider to the time I want the display to sleep after, and I had to set the "Put display to sleep when computer is inactive for" slider in the power management preferences to the same value.

It turned out that this made the display sleep after twice the time I expected, so it seems these values are additive. You can't "set session as idle after" less than 1 minute, so you'll have to subtract a minute from the time you actually want in the power management dialog, or share the time out in some other fashion. Bizarre and awkward.

The "raw" GNOME equivalent on my Debian box at work is clearer, with the display-related power management controls on a tab in the "screensaver" preferences. Ubuntu's quite hit and miss when it comes to their supposed simplifications. Sometimes they do a good job, and other times they make something moderately awkward even more confusing. This is a perfect example of how letting implementation details show through can ruin an interface.

While I'm on the subject of Xorg not being as bad as its friends make it look, I found out that you can disable the stupid "fail to start if there's no mouse attached at boot time" behavior. Add this to your "ServerLayout" section:

Option "AllowMouseOpenFail" "True"

Mac OS and Windows, of course, both do the right thing automatically.

And one final display-related tip: don't be mislead by Apple's claim that "Any dual- or quad-core Power Mac G5 supports two Apple Cinema Displays, including dual-link DVI for one 30-inch model." (http://www.apple.com/displays/specs.html). My dual G5 doesn't have dual-link DVI. It supports a 30" display in the sense that it can display on it, but it doesn't support the 2560x1600 resolution you want. Also, don't assume that you can take a quick glance at the Mac Pro specifications, see "7300 GT" and assume that any 7300 GT has dual-link DVI (even though they all seem to have dual DVI, which is something different entirely). If your graphics card doesn't explicitly say "dual-link DVI" (not "dual DVI"), you'll be disappointed. Apple are pretty clear about the need for dual-link DVI, and the store and box specifications seem to be correct. But that claim on the displays' "tech specs" page is misleading. (The trick, in case you didn't notice, is that they mean "dual-core G5", not "dual G5". What is it with the word "dual"? Someone needs a kick in the plums.)

If you're running Xorg with a 30" display connected and want to know why you're not getting 2560x1600, check /var/log/Xorg.0.log and ensure that it mentions "Internal Dual Link TMDS".

If it does, cull any crap from your xorg.conf and just let it use the EDID information.

If, on the other hand, it says "Single Link", it's a trip to Fry's for you, my boy.


HashMap type safety leaves something to be desired

I hate puzzles, so I'll tell you straight out that though you might think this code shouldn't compile, it does, and prints "null" twice:

import java.awt.Color;
import java.util.HashMap;

public class test {
public static void main(String[] args) {
HashMap<Color, String> m = new HashMap<Color, String>();
m.put(Color.RED, "red");

HashMap<Long, String> n = new HashMap<Long, String>();
n.put(100L, "red");

I've actually seen someone make this mistake, and want me to explain to them why in hell the Java compiler let them pass an object that wasn't of type K to HashMap<K, V>.get. Wasn't the very reason they rewrote their code to use generics, they asked, to be protected from this kind of mistake?

The reason this compiles is that although put has the signature you'd expect, get (and containsKey, containsValue, and remove) don't. They all take parameters of type Object.

It's the usual reason something's broken: backwards compatibility. Neal Gafter brushes it off thus:

The reason the argument type is Object and not K is that existing code depends on the fact that passing the "wrong" key type is allowed, causes no error, and simply results in the key not being found in the map. This is no worse than "accidentally" trying to get() with a key of the right type but the wrong value. Since none of these methods place the key into the map, it is entirely typesafe to use Object as the method's parameter.

Backwards compatibility is all well and good, but I can hear Stroustrup wondering why we have to pay for things we don't use. I keep my code up-to-date, and yet I have to suffer this breakage for the benefit of the guy who lost his source in 1997? Why don't my "-source 1.5 -target 1.5" arguments to the compiler let me have libraries without bugs or infelicities from years ago?

The "no worse" bit is particularly cheeky, slippery language-lawyer talk, since the two classes of error are not comparable (looking up a non-existant key isn't even necessarily an error, and one of these classes of error is something the compiler should catch for us; no C++ compiler would accept incorrect code like the above). Gafter implies that the sole purpose of generics, and the only guarantee from "type safety" is that you won't have a malformed collection. Which is a good thing, and better than nothing, but disregards the concerns of the users (rather than the authors) of the collections classes.

It's especially cheeky when you consider the second example, where our arch-enemy autoboxing lends a hand. You might think the exact example (autoboxing choosing the wrong type for the literal) is unlikely, and I'd be inclined to agree (though I wouldn't agree that that's an excuse for the compiler to miss it), but I've seen someone make a similar mistake, where they started with an index into an indexed collection and should have got the corresponding element and looked the element up in a hash, but accidentally tried to look up the index in the hash instead. Nonsense code of exactly the kind that generics and static typing are supposed to protect you from, and not so much as a run-time error; just wrong behavior.

Update: Neil Gafter responds:

We would love to have made Map.get and remove take K instead of Object, and we tried that. Unfortunately, it broke lots of genuine, correct, production customer code which depends on the existing behavior, which was after all specified in the interface before it was generified.

He also provides one example of the kind of code that was already out there:

One kind of example goes something like this: You have a system in which you handle lots of objects of type Foo. There is some particular subtype of Foo called Bar that you sometimes cache in a collection. Sometimes some of your Foo objects become "out of date" and have to be flushed from any caches. So you have a

Collection<Bar> barCache;
Collection<Foo> outOfDateThings;

and you just

for (Foo foo : outOfDateThings) barCache.remove(foo);

(Ignoring the fact that I used the new looping construct) This kind of code was clearly correct and typesafe before the collection classes were generified. The code used the collection classes in ways that only depended on specified behavior.

You have to decide for yourself if such examples are convincing.

His most interesting comment, though, was this:

By the way, what you lose in "checking" you gain in flexibility; folks using the (existing) relaxed Map API can actually do useful things that the (hypothetical) stricter version doesn't allow.

Which has me shaking my head again, and Stroustrup wondering why we're all paying for something even when we don't need it. I still think this is an odd way to look at it, because it's the kind of thing you usually hear from the dynamic typing crowd. The word 'checking' in quotes? Argument by appeal to flexibility?

Ricky Clarkson and Thomas Hawtin both think it's an important decision because it makes wildcards more useful than they would otherwise be. Even if there were no legacy code, they want code like



    List<? super Integer>.contains(5)

to work. Hawtin imagines an alternate universe where we could have our cake and eat it, and say something like this:

    public V get (? super K key) { // not valid Java

Given the number of times I've talked about C++ above, it's worth mentioning Stroustrup and Dos Reis' Specifying C++ Concepts, which talks about the author's attempts to describe "concepts" to the computer. (In the C++ world, "concept" is the name for a set of type requirements. At the moment these are described in English, in documentation, for human consumption only. You'll get a compile-time error if a template instantiation leads to invalid code, perhaps because a type you used doesn't support a required operation. Other times you'll just get run-time errors, similar to the problems you can get in Java from bad equals or hashCode implementations.)

My real concern for Java, though, as I said above, is about Java's future when there's this strong promise of backwards compatibility but no corresponding mechanism for fixing old decisions. It would be a shame to have to move house just because the toilet won't flush.

On a lighter note, I was caught out recently myself, too. As I typed something analogous to the following, I thought my editor's code coloring was broken:

public class C {
public static void main(String[] args) {
/* System.err.println("*/"); */

The compiler confirmed, though, that there was an unterminated string. The temptation is to say "stupid compiler!", because there "obviously" isn't: anyone can see that there's a valid string literal in there that just happens to contain the characters that terminate Java block comments.

Neal Gafter recently wrote, in the context of a proposal to add closures to Java, about "Gilad's insistence that we comply with Tennent's Correspondence and Abstraction Principles (described in detail in the now out-of-print book Principles of Programming Languages by R.D.Tennent)". [Embarrassing that a great book you remember from university should now be out of print, even if it was a decade old in your day.] So here, for example, you'd want to be able to block-comment or uncomment any piece of code without changing its well-formedness.

Unfortunately, the compiler doesn't magically know where a comment ends. So it has no choice but to just munch through characters until it next sees "*/", causing it to read the body of main as a comment followed the unterminated string literal "); */ (Java string literals can't contain unescaped newlines, so the lexical analyzer recognizes the problem at that point). Commenting isn't really an abstraction mechanism, but you can see how this might upset Tennent. There's no good solution, though, because block comments are often required precisely because the code they contain isn't well-formed. So we can't expect the compiler to parse the content of block comments looking for string literals.

There's a work-around, of course, that gives you code that works with or without the block comment, but this kind of intrusion is always unwelcome, even when there's no solution (as far as I'm aware) to the underlying problem:

public class C {
public static void main(String[] args) {
/* System.err.println("*" + "/"); */


Highlighting find matches in a JTextPane HTMLDocument

This is pretty obvious, but my first implementation was wrong, and my attempt to ask Google for a quick answer didn't work.

I was using JTextPane to display HTML, and I wanted to implement Firefox-like find functionality, where all the matches get highlighted. My preferred editor works like this, but it uses a custom text component (a kind of high-performance multi-color JTextArea). My favorite terminal emulator works like this too, but has a different kind of custom text component, suited to terminal emulation.

My first implementation simply invoked JTextPane.getText, found the matches, and added highlights at the offsets returned by the Matcher. The trouble was, these are offsets into the source HTML, but the Highlighter works in terms of offsets into the visible text.

What you need to do is get an HTMLDocument.Iterator that iterates over just the "content" text. You can use the offsets the iterator gives you to work out where the highlighter goes. The code looks like this:

Highlighter highlighter = textPane.getHighlighter();
HTMLDocument document = (HTMLDocument) textPane.getDocument();
for (HTMLDocument.Iterator it = document.getIterator(HTML.Tag.CONTENT);
it.isValid(); it.next()) {
try {
String fragment = document.getText(it.getStartOffset(),
it.getEndOffset() - it.getStartOffset());
Matcher matcher = pattern.matcher(fragment);
while (matcher.find()) {
highlighter.addHighlight(it.getStartOffset() + matcher.start(),
it.getStartOffset() + matcher.end(),
} catch (BadLocationException ex) {

If you need a find dialog and find/find previous/find next actions, you can find it all in salma-hayek, and just need one line in your code:


One other thing, while I'm on the subject of Highlighter... For some reason, most example code involves a useless subclass of DefaultHighlighter.DefaultHighlightPainter. Here's an example from the fount of all bad Java code, the Java Almanac:

// Don't do this! This is stupid!

// An instance of the private subclass of the default highlight painter
Highlighter.HighlightPainter myHighlightPainter = new MyHighlightPainter(Color.red);

// A private subclass of the default highlight painter
class MyHighlightPainter extends DefaultHighlighter.DefaultHighlightPainter {
public MyHighlightPainter(Color color) {

All you need, as is obvious from the above, is something like:

Highlighter.HighlightPainter myHighlightPainter =
new DefaultHighlighter.DefaultHighlightPainter(Color.RED);

I've no idea why this cargo-cult nonsense persists. The Java Almanac version is a relatively mild form. I've seen more verbose variants, including cases where people subclass and replace the default Highlighter just to change the HighlightPainter, breaking selection highlighting for no obvious reason. Even when a custom HighlightPainter is necessary, a custom Highlighter probably isn't.

So if you come across that kind of thing and wonder what you're missing, don't worry: it's not you who's mad.