Holy cow, I wrote a book!
The hollow brush is a brush that doesn't do anything.
You can use it when you're forced to use a brush but you don't
As one example, you can use it as your class brush.
Then when your program stops responding and Windows decide
to do the "white flash" (see yesterday's entry),
it grabs the hollow brush and ends up not drawing anything.
(At least, that's how it worked on Windows 2000. Things may
be different on XP.)
says his daughters hate his music and change the channel whenever
Knight Rider comes on the TV.
Okay, I defended the Germans last week, but this one baffles even me.
Do the Germans not realize that David Hasselhoff is a joke?
Er war ein unbeudentender Schauspieler in einem blöden
Fernsehprogramm. Ihm wurde die Schau von einem Auto gestohlen!
(And for those who still want
their Knight Rider fix, you can
check out this movie of some people who
installed remote control hydraulics in a 1982 Toyota Camry and drove
it around the desert, just like the Knight Rider title sequence.)
It was kind of a strange feeling when I encountered Polish notation
in logic class. Finally I got to see the forwards version of what
I had been doing in reverse for so many years!
here's a classic example of German as RPN, hidden in a web page
on the subject of Dutch word order. Consider
the clause "... that Frank saw Julia help Fred swim."
In German, that would be expressed as
You can create this sort of constructing in English too,
but nobody does this unless they are trying to cause trouble:
"The rat the cat the dog chased caught died."
English also gets somewhat unpredictable if you decide to
start the sentence with something other than the subject:
It's like English is struggling to decide whether
it wants to hang out with its Germanic buddies and
use X-V-S or strike out on its own and be an S-V language.
I found German an easy language to learn because it is
much more logical, much less capricious. "The verb goes
in second position, the adjective goes in front of the noun."
"But what if the adjective is really long?"
"Tough. Goes in front. Because that's where adjectives go."
Swedish (at least to my unaccustomed ears)
leans more towards the capricious
end of the scale.
What's the difference between "från"
and "ifrån" and "i från"?
It's probably one of those subtleties that I will never learn.
The lack of inflectional complexity in English is made up for
by its much more complicated structural form. English word order is nuts.
Why does the temporal adverb go in front of the verb in one case,
but after it in another?
And it comes in the middle of the verb in a third case!
(Okay, technically you can put the adverb in any of those places,
but it sounds stilted or
changes the meaning of the sentence subtly. Try explaining
that to a student of English and they will merely shake their head
Or consider the placement of the verb particle in English
(which corresponds to the German separable prefix):
Now put these two rules together and you find that
seemingly minor changes to a sentence
(changing one temporal adverb for another, replacing a noun with a pronoun)
has a radical effect upon sentence structure.
The sentence structure goes from
How is anybody expected to learn this?
In German, the word order is predictable.
All of these sentences would be structured as
"<subject> <verb> <object> <frequency> <prefix>".
For added fun, add "carefully" to the sentence
and watch everything moves around again:
"I don't often pick it up carefully."
I find it ironic that when a Germanic language
discards inflectional complexity
(making it harder to see the relationship among the words in a sentence),
it compounds the difficulty by adding greater structural complexity
(making it even harder still
to see the relationship among the words in a sentence).
Twain complained about all the exceptions.
Actually I find that German is comparatively lacking in exceptions;
the rules tend to be followed fairly uniformly.
Twain complains about "parentheticals",
but it is the parentheticals that make English so crazy.
In German, the rule is very simple:
"The adjective comes before the noun". Even if the
adjective happens to be complicated.
"The to-its-winter-home-flying goose."
Whereas in English, the rule is "The adjective comes before
the noun, unless the adjective would sound better if it came
after the noun."
"The goose flying to its winter home" but "The slowly-flying goose".
Try explaining that to your dad.
English, now that's where all the crazy exceptions hang out.
For example, the adverb can be moved to the front for emphasis
"Rarely" is one of those exceptions that require inverted word order.
And "always" is an even weirder exception:
You can't start a declarative sentence with it at all!
(Though you can start imperatives with it. Go figure.)
Swedish used to be a more heavily inflected language,
but it has been shedding its inflectional complexity over the centuries.
(The number of genders reduced from three to two;
special inflective forms for plurals have been removed;
the dative case is now obsolete...)
Swedish (like English) has been making the verb forms and word order
The word "inte" ("not") goes immediately after the finite verb,
except when it doesn't. And sometimes it changes to "ej" or "ikke"
for reasons I have yet to determine.
Or at least, that's what people would claim.
Actually, Windows is painting your window with your class
background brush. Since most people use COLOR_WINDOW and since
COLOR_WINDOW is white in most color schemes, the end result is
a flash of white.
Why paint the window white? Why not just leave it alone?
Well, that's what it used to do, but the result was that
the previous contents of the screen would be shown where
the window "would be". So suppose you were looking at
Explorer, and then you restored a program that stopped
responding. Inside the program's main window would be...
a picture of Explorer. And then people would try to
double-click on what they thought was Explorer but was
really a hung program.
In Windows XP, the behavior for a window that has stopped
painting is different. Now, the system captures the pixels
of the unresponsive window and just redraws those pixels
if the window is unable to draw anything itself.
Note, however, that if the system can't capture all of
the pixels - say because the window was partially covered -
then the parts that it couldn't get are filled in with
the class brush.
After DirectX 3 was released, development on two
successor products took place simultaneously:
a shorter-term release called DirectX 4 and
a more substantial longer-term release called DirectX 5.
But based on the feedback we were getting from the game
development community, they didn't really care about
the small features in DirectX 4; what they were much more
interested in were the features of DirectX 5.
So it was decided to cancel DirectX 4 and roll all of its
features into DirectX 5.
So why wasn't DirectX 5 renamed to DirectX 4?
Because there were already hundreds upon hundreds of
documents that referred to the two projects as
DirectX 4 and DirectX 5. Documents that said things
like "Feature XYZ will not appear until DirectX 5".
Changing the name of the projects mid-cycle was
going to create even more confusion. You would
end up with headlines like
"Microsoft removes DirectX 5 from the table - kiss
good-bye to feature XYZ" and
conversations reminiscent of
"I have some email from you
saying that feature ABC won't be ready until DirectX 5.
When do you plan on releasing DirectX 5?"
"We haven't even started planning DirectX 5; we're
completely focused on DirectX 4, which we hope to
have ready by late spring."
"But I need feature XYZ and you said that won't be
ready until DirectX 5."
"Oh, that email was written two weeks ago.
Since then, DirectX 5 got renamed to DirectX 4,
and DirectX 4 was cancelled."
"So when I have a letter from you talking about DirectX 5,
I should pretend it says DirectX 4, and when it says DirectX 4,
I should pretend it says 'a project that has since been cancelled'?"
"Right, but check the date at the top of the letter,
because if it's newer than last week, then when it says
DirectX 4, it really means the new DirectX 4."
"And what if it says DirectX 5?"
"Then somebody screwed up and didn't get the memo."
"Okay, thanks. Clear as mud."
For example, there were a few programs that responded to
the LVN_GETDISPINFO notification
by overflowing the LVITEM.pszText buffer, writing more
than LVITEM.cchTextMax characters.
Another responded to
by overflowing the pszName buffer, writing more than cchMax characters.
Fortunately, in both cases, the overflow was only one character,
so we were able to fix it by over-allocating the buffer by one and
underreporting its size. That way, if the program overflows the
buffer by one, it doesn't corrupt anything.
Another one overflows one of its own stack buffers if you right-click
on a file whose name is longer than MAX_PATH.
(These files are legal but are hard to create or manipulate.)
Not much we can do to prevent that one.
I write code that is Win64-compliant as a matter of course
since all code in Windows must be Win64-compliant.
Writing noncompliant code is as foreign to me as
it would be for a chess player to consider
the ramifications of an illegal move.
It doesn't even enter my mind.
The ia64 does not have an absolute addressing mode.
Instead, you access your global variables through the r1
register, nicknamed "gp" (global pointer).
This register always points to your global variables.
For example, if you had three global variables, one
of them might be kept at [gp+0], the second at [gp+8]
and the third at [gp+16].
(I believe the Win32 MIPS calling convention also used this technique.)
On the ia64,
there is a limitation in the "addl" instruction: You can only
add constants up to 22 bits, which comes out to 4MB.
So you can have only 4MB of global variables.
Well, it turns out that some people want more than 4MB of
global variables. Fortunately, these people don't have
one million DWORD variables. Rather, they have a few
really big global arrays.
The ia64 compiler solves this problem by splitting global
variables into two categories, "small" and "large".
(The boundary between "small" and "large" can be set by
a compiler flag. I believe the default is to treat anything
larger than 8 bytes as "large".)
The code to access a "small" variable goes like this:
addl r30 = -205584, gp;; // r30 -> global variable
ld4 r30 = [r30] // load a DWORD from the global variable
(The gp register actually points into the middle of your global
variables, so that both positive and negative offsets can be used.
In this case, the variable happened to live at a negative offset
By comparison, "large" global variables are accessed through a
two-step process. First, the variable itself is allocated in a
separate section of the file. Second, a pointer to the variable
is placed into the "small" globals variables section of the
module. As a result, accessing a "large" global variable requires
an added level of indirection.
addl r30 = -205584, gp;; // r30 -> global variable forwarder
ld8 r30 = [r30];; // r30 -> global variable
ld4 r30 = [r30] // load a DWORD from the global variable
If you leave the size of an object unspecified, like
extern BYTE b;
On the other hand,
if you misdeclare the object as being small when it is actually
large, then you end up in trouble.
For example, if you write
extern BYTE b;
extern BYTE b;
So don't do that. When you declare a variable, make sure to declare
it accurately. Otherwise the ia64 will catch you in a lie,
and you will pay.