All nice and fancy, but I'm going to have to side on SMadsen on this one... The ``answer'' to your challange may not be right there in plain code but man, you gotta love this explination.
osnap binary decimal powers
name representation do. of two
---------------------------------------------
non 0000 0000 0000 0000 0
end 0000 0000 0000 0001 1 2^0
mid 0000 0000 0000 0010 2 2^1
cen 0000 0000 0000 0100 4 2^2
nod 0000 0000 0000 1000 8 2^3
qua 0000 0000 0001 0000 16 2^4
int 0000 0000 0010 0000 32 2^5
ins 0000 0000 0100 0000 64 2^6
perp 0000 0000 1000 0000 128 2^7
tan 0000 0001 0000 0000 256 2^8
nea 0000 0010 0000 0000 512 2^9
qui 0000 0100 0000 0000 1024 2^10
app 0000 1000 0000 0000 2048 2^11
ext 0001 0000 0000 0000 4096 2^12
par 0010 0000 0000 0000 8192 2^13
toggle 0100 0000 0000 0000 16384 2^14
not used 1000 0000 0000 0000 32768 2^15
Example: end+int+ins = 1+32+64 = 97
end 0000 0000 0000 0001 = 1
int 0000 0000 0010 0000 = 32
ins 0000 0000 0100 0000 = 64
-----------------------------------
0000 0000 0110 0001 = 97
Now look for intersection, i.e. bit 5.
Run through each bit and do AND comparison
for each bit in the integers.
AND will return 1 if and only if both bits
are 1, otherwise it will return zero. The
truth table for AND looks like this:
| 0 1 | false true
------- or in boolean: -------------------
0 | 0 0 false | false false
1 | 0 1 true | false true
So, let's apply this to the integers:
0000 0000 0110 0001 = 97
AND 0000 0000 0010 0000 = 32
----------------------------
0000 0000 0010 0000 = 32
So, 97 AND 32 = 32, because bit 5 is set in
both integers.
Let's look for quadrant osnap, i.e. bit 4:
0000 0000 0110 0001 = 97
AND 0000 0000 0000 1000 = 16
----------------------------
0000 0000 0000 0000 = 0
Because no bits in the integers "match",
AND will return zero for every pair of bits,
so 97 AND 16 = 0
Therefore, you are actually looking for a
number within a number, and saying
If (varSnap AND 32) = 32 Then MsgBox "Inters is On"
is the correct way instead of
If varSnap = 32 Then MsgBox "Only inters is On!"
And for goodness sake, lets not forget this one as well.
Here is some chitchat on setting and clearing bits. Sorry about the everything-in-courier thing.
Setting bits.
The truth table for OR looks like this:
| 0 1 | false true
------- in boolean: ------------------
0 | 0 1 false | false true
1 | 1 1 true | true true
OR returns 1 if both or just one of the input bits are 1. What can we
use that for?
Say we want to set a certain OSNAP. Well, because OR returns 1 if
just one of the input bits are set, we can ensure that as long as we
input a set bit it will return a set bit no matter if the other input
bit is set or not set (1 or 0).
Example:
Osnap is now: end+ins = 1+64 = 65
Osnap wanted: end+int+ins = 1+32+64 = 97
The missing bit is the 5th bit representing the value 32, so we can
try set up an expression and see what happens. varSnap is simply the
osnap value returned by OSMODE:
newSnap = varSnap OR 32
0000 0000 0100 0001 = 65
OR 0000 0000 0010 0000 = 32
-----------------------------------
0000 0000 0110 0001 = 97
Mission accomplished. We can now put it into a function and test it
(excuse my lack of VBAbilities):
Public Function SetBit(ByVal source As Long, ByVal newBit As Long) As Long
SetBit = source Or newBit
End Function
Public Sub SetInters()
Dim varSnap, inters, dest As Long
varSnap = ThisDrawing.GetVariable("OSMODE")
inters = 32
dest = SetBit(varSnap, inters)
ThisDrawing.SetVariable "OSMODE", dest
End Sub
Of course it doesn't matter what the current OSMODE is. End+Ins was
just used to show the calculation. This operation does not mess with
bits already set because two set bits will simply return a set bit.
So if Intersection was set already, it doesn't harm anything.
To clear bits.
Given the truth tables for AND it should become obvious that
negating one bit has an affect:
A AND B: A AND (NOT B):
| 0 1 when negating | 0 1
------- second input bit: -------
0 | 0 0 0 | 0 0
1 | 0 1 1 | 1 0
Because this operation only returns 1 if the first input bit is 1,
we can use it to clear any bit within an integer. Say we want to
turn off Intersection, i.e. bit 5 in OSMODE, we can set up this
expression and test it:
newSnap = varSnap AND (NOT 32)
First, let's find (NOT 32).
NOT 0000 0000 0010 0000 = 32
-------------------------
1111 1111 1101 1111 = (doesn't matter)
Easily done - 1 becomes 0 and vice versa. Only 16 bit are shown here,
so the decimal representation doesn't matter (it didn't matter if all
32 bit were shown, anyway)
Now, take varSnap AND (NOT 32):
0000 0000 0110 0001 = 97
AND 1111 1111 1101 1111 = (still doesn't matter)
-------------------------
0000 0000 0100 0001 = 65
Mission accomplished. Bit 5 is gone. Again, because the calculation
relies on AND, it doesn't affect the result if the bit we are masking
was already turned off. If intersection was already turned off,
trying to clear it has no effect:
0000 0000 0100 0001 = 65
AND 1111 1111 1101 1111 = (still doesn't matter)
-------------------------
0000 0000 0100 0001 = 65
An simple function to clear a bit could be:
Public Function ClearBit(ByVal source As Long, ByVal bit2clear As Long) As Long
ClearBit = source And (Not bit2clear)
End Function
Other ways to do this is to use XOR as decribed next, or to make a
simple subtraction like this:
Public Function ClearBit2(ByVal source As Long, ByVal bit2clear As Long) As Long
ClearBit2 = source - (source And bit2clear)
End Function
The home assignment is to figure out why this only affects the bit
we want to clear.
Flipping bits.
XOR is funny. It's related to OR (XOR is called exclusive OR - hence
the X - while OR is called inclusive OR - just with no I) and the
truth table looks like this:
| 0 1 | false true
------- in boolean: -------------------
0 | 0 1 false | false true
1 | 1 0 true | true false
A flipping "motion" can already be seen in the truth table. It
returns 1 if only one of the input bits are 1.
Want to construct XOR with AND,OR and NOT? Easy:
(OR (AND A (NOT B))(AND (NOT A) B))
Seriously, say you have an OSMODE of 97 (again) and you want to flip
bit 5:
0000 0000 0110 0001 = 97
XOR 0000 0000 0010 0000 = 32
-----------------------------------
0000 0000 0100 0001 = 65
Away intersection goes! This is the precise same thing as clearing a
bit like above, except that if the first input bit is different than
the second input bit, it will affect the resulting bit. For example,
if intersection was already off it will turn it on instead of leaving
it off - hence the word "flip":
0000 0000 0100 0001 = 65
XOR 0000 0000 0010 0000 = 32
-----------------------------------
0000 0000 0110 0001 = 97
With XOR you can flip all bits at once. So if you want to remove
bit 0 and 5 at once, you can XOR 97 and 65. But you can also flip
back by reversing the operation. A sample flip-function:
Public Function FlipBit(ByVal source As Long, ByVal bits2flip As Long) As Long
FlipBit = source Xor bits2flip
End Function
Once again, Thank you Stig. You are a true genius.