Wandering Thoughts archives

2010-05-22

How I fixed Google's search results redesign

I really dislike Google's redesign of their search results, because they commit one of my great irritations; they put site navigation on the left side (where it cuts off content in narrow windows) instead of on the right (or on the bottom, or nowhere). After a few days of staring at the new design and grinding my teeth, I decided to fix it.

Since I use Firefox, the modern way of fixing this is probably a Greasemonkey script. However I don't use Greasemonkey for various reasons; partly because I use NoScript and I don't know how the two would interact, and partly because I've never wanted the kind of high-powered rearrangement of web pages that is Greasemonkey's stock in trade (if a website needs that much rearrangement to be nice, I'm not likely to use it to start with). So my weapon of choice in this situation is the Stylish extension, which lets me add and override CSS settings.

(The drawback to Stylish is that it only really works well if the website has annotated their HTML with class and ID labels, so that you can precisely target your CSS restyling. Fortunately this is usually the case when people are doing obnoxious styling tricks that I want to override, since they're usually using CSS to style things in the first place.)

The problem with Stylish-based alterations is figuring out what to change, which requires reverse engineering the HTML and CSS to see what creates the bad design in the first place. Usually I can read things by hand, but Google uses such densely packed HTML and CSS that I gave up and temporarily installed Firebug and used it to pick through the mess. The net result is the following Stylish style:

@namespace url(http://www.w3.org/1999/xhtml);

@-moz-document url-prefix("http://www.google.com/search") {
  div #leftnav {display: none !important;}
  div #center_col {margin-left: 0px !important;}
}

For the most part this is brute force CSS bashing; it first deletes the left navigation area and then overrides an attempt by the search results to keep reserving space for it. The most useful thing (and a feature not directly exposed by Stylish) is using the url-prefix option to force this style to apply just to Google search results instead of everything at Google.

(See the @-moz-document documentation for a tiny bit more on this. Stylish directly exposes the other two options it has.)

web/FixingGoogleRedesign written at 23:52:00; Add Comment

Why I'm wrong about what sort of APIs C's stdargs allows

One of the things that blogging gives me is the chance to be very wrong in public. Yesterday, I claimed that C's stdargs didn't let you peel some arguments off the front of a va_list and then pass the shortened list to another function, such as vprintf(). Well, no, and now I'll tell you why I'm wrong.

I'm clearly wrong in practice on x86 Unix machines with gcc, as a simple test program easily demonstrated once a commentator raised doubts and I bothered to check. But I also believe that I'm wrong even in theory and that this sort of manipulation of va_list likely has to be supported by any spec-compliant C compiler. While this is not spelled out directly in the documentation I've read, I think that it arises by implication from things like the Single Unix Specification stdarg page.

(A disclaimer: I haven't read the ANSI/ISO C standard, so this may be clearly spelled out there.)

First, assume that you can write a standards-compliant C function that accepts a va_list argument and works directly with it, an equivalent of vprintf() or the like. The only way this function has to extract arguments from the va_list is with va_arg(), which it's allowed to use. va_arg() requires that you first call va_start().

However, our va_list receiving function cannot call va_start() itself; va_start() must be invoked with the identifier of the rightmost parameter before the ... in the varargs function definition, which exists only in the context of the caller of our function. So the caller must call va_start() before invoking our function, and in fact is the only function that can. And once you call va_start(), the behavior of va_arg() is quite well specified and contains no mention of the va_list being reset when you call a function; each time you call va_arg(), you advance the va_list to the next parameter (until you run out).

Hence I believe that the C standard almost certainly requires that if you call va_arg() and then pass the va_list to another function, that function sees the va_list just as you would and gets the same results from calling va_arg() that you would. Peeling arguments off your va_list and then calling a v* function with the remainder is perfectly spec-compliant behavior.

This still leaves the C stdarg stuff moderately constrained, but it's less constrained than I thought.

Sidebar: Why you have to reset va_list after function calls

va_list is an opaque type that is effectively an iterator, and implementations are free to make it have internal state that is manipulated by va_arg(). Thus, when you call a function and pass it a va_list, that function may manipulate the internal state of your iterator and leave it in some random state, or simply at the end of the varargs parameters. So you have to reset it in order to be able to use it again yourself.

(This idea is achingly familiar to anyone who has ever passed iterators around in Python.)

programming/CStdargWhyWrong written at 00:56:06; Add Comment


Page tools: See As Normal.
Search:
Login: Password:
Atom Syndication: Recent Pages, Recent Comments.

This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.