I don't actively use C and haven't really done much with it. Usually I can figure out enough to do the same thing in assem. This one's got me.

I've been playing with scroll bars. This is from the scrolling text example in Win32.hlp:

GetTextMetrics (hdc, &tm);
xChar = tm.tmAveCharWidth;
xUpper = (tm.tmPitchAndFamily & 1 ? 3 : 2) * xChar/2;
yChar = tm.tmHeight + tm.tmExternalLeading;

What's up with the & 1 ? 3 : 2 thingy...

Posted on 2001-09-24 14:35:34 by S/390
that statement works as folows:

var = condition ? :

ie teh condition is evaluated and if it is true (ie non-zero) then the value to the left of the ":" is assigned to hte variable, else teh other value is assigned to the variable if teh condition is false

btw...i think the tmpitch & 1 bit is a logical and or something
Posted on 2001-09-24 14:48:07 by SubHuman
SubHuman is right, I think this line:

xUpper = (tm.tmPitchAndFamily & 1 ? 3 : 2) * xChar/2;

would become something like this:

; assume eax = xChar here
mov ecx, eax ; xChar
shr eax, 1 ; xChar / 2
.IF tm.tmPitchAndFamily & 1
add ecx, eax ;ecx = xChar + xChar /2 = (xChar * 3/2)
;else: ecx = xChar = 2 * xChar/2
; ecx is xUpper now

Posted on 2001-09-24 15:53:34 by Thomas
The "?" syntax might seem a bit weird, but GCC with the right commandline
option (to enable support for p6 and upwards, which will obviously
break backwards compatibility) is able to generate code using
CMOV when you use it... which is pretty neat :).
Posted on 2001-09-24 15:59:47 by f0dder
Thanks guys. Hopefully I'll get back to playing with scroll bars shortly, as soon as I figure out why CICS keeps crashing on our mainframe.

Damned computers... :)
Posted on 2001-09-25 03:23:44 by S/390
I was always taught

(expression) ? statement1 : statement2

if expression is true, execute statement1, else execute statement2.

maybe im wrong..
Posted on 2001-09-25 07:58:25 by vcv
Because of the relativly simple nature of the code (multiply by 2 or 3), you can get by without CMOV in this case!

Be warned, its a bit messy!

mov ecx, tm.tmAveCharWidth
mov eax, ecx
and ecx, 0FFFFFFFE ; ecx = int(tm.tmAveCharWidth / 2) * 2 (clear the bottom bit)!
sar eax, 1 ; eax = tm.tmAveCharWidth / 2
xor edx, edx ; edx = 0
test tm.tmPitchAndFamily, 1
setz dl ; If tm.tmPitchAndFamily & 1 == 0 edx = 1 else edx = 0
dec edx ; edx = 0 or edx = 0xFFFFFFFF
and eax, edx ; eax = 0 or edx = tm.tmAveCharWidth / 2
add eax, ecx ; eax += int(tm.tmAveCharWidth / 2) * 2

eax holds the value of xUpper!

Posted on 2001-09-25 10:21:39 by Mirno
Of course you can get by without the need of cmov, duh :). And of
course it's only used if you tell the compiler to use it. Plus, I bet the
compiler only uses it when it can see it will matter.
Posted on 2001-09-25 10:27:46 by f0dder
When will it not matter?
CMOV is a great instruction, its just a pity that its so new!
It was a demonstration that you can get the same result, but it'll take an extra register, and several extra cycles!

The only other thing I should have pointed out is that:
(x/2) * 2 != x

At least not when dealing with integers! But I'm just very pedantic to point it out!

Posted on 2001-09-25 11:28:27 by Mirno
Mirno: I realized that, but I wonder if it matters. I don't know if there's a reason to use integers here. Wouldn't assuming (x / 2) * 2 = 2 be more precise?
I agree that my code isn't exactly the same as the C one but does the C code use integers intentionally or not?

Posted on 2001-09-25 12:18:31 by Thomas
If you use integers, C uses integers :]. In other words, unless you're
doing float casts, the C compiler will perform DIV when working with
integer data types (unless it chooses to optimize to SHR)
Posted on 2001-09-25 12:24:46 by f0dder