Hi, Johannes.
Thanks, this is very nice. Some more comments and suggestions.
Why do you need MATCH_PREFIX_IGNORECASE instead of just using MATCH_PREFIX | MATCH_IGNORECASE ?
Is MAX_WINDOW_NAME_LENGTH == 42 reasonable? The goal isn't to enforce short window names, only to protect against strings not being null-terminated. Why not 1024 or even 4096? Or maybe something already enforces 42?
I'm a fan of descriptive variable names. So compare_length is more descriptive to me than cmplen. This is motivated by seeing abbreviations that were obvious after being explained but that required asking.
Many a bug can be prevented by using braces even on one line blocks where they are not needed. The mechanism is that someone adds a statement later on and misses the missing braces.
window_name returns a char* that is not a copy (i.e., you don't own it). So modifying it isn't such a good idea.
Can you use a function pointer for your compare function so that you don't need to have the pre-processing block?