> I know I can add children to an object and make them either the first or
> last child, but how do I put it in a specific position? The concepts book says:
>
> CCF_REFERENCE
> This field consists of the lower 15 bits of the word and is a
> positive integer representing the position of the child in its
> parent's child list. This number cannot be greater than 32767
> (0x7fff hex). If the number given is greater than the number of
> current children, the child will be assumed to be last. For
> example, a CCF_REFERENCE of five would specify the fourth
> child of the parent object, or the last child if there are fewer
> than five children currently. When specifying a position for
> CCF_REFERENCE, use the CCF_REFERENCE_OFFSET (using
> the shift operator).
>
> But I don't understand how 5 would be the fourth child. The other way around
> would make sense because then it would be zero based. This would have to be
> 2 based.
You are correct, this is a error in the docs -- "5" would specify the 6th
child, and "4" specifies the 5th child, just as you thought. A bug report
has been filed.
> Basically what I want to do is something like this:
>
> optr parent, oldchild, newchild;
> word position;
>
> position = @call parent::MSG_GEN_FIND_CHILD(oldchild);
> @call parent::MSG_GEN_REMOVE_CHILD(oldchild, 0);
> @call parent::MSG_GEN_ADD_CHILD(newchild, position);
>
> I would think that would be how you do it, but the docs have me confused. I
> haven't had a chance to try it yet. I probably need to OR a flag in also or
> something like that.
You're almost correct, syntactically, and what you've got there will
work, but to be perfectly correct, make this slight change:
> optr parent, oldchild, newchild;
> word position;
>
> position = @call parent::MSG_GEN_FIND_CHILD(oldchild);
> @call parent::MSG_GEN_REMOVE_CHILD(oldchild, 0);
> @call parent::MSG_GEN_ADD_CHILD(newchild, position);
The second parameter of MSG_GEN_REMOVE_CHILD are the CompChildFlags.
Note that this includes not only the position of the new child (which
I see that you are trying to set), but also the flag CCF_MARK_DIRTY,
which tells the system "this object's instance data has just changed"
(you just changed its GI_comp field), "please mark it dirty so this
object will be correctly saved to state." [For the CompChildFlags,
see the Data Structures section of the Routines book.]
So you'll want to include the CCF_MARK_DIRTY flag.
Also, when setting the child position, if it's the new first or last
child, you can use the pre-defined constants CCO_FIRST or CCO_LAST;
otherwise, you can provide a word value (as you have done, above, using
the variable "position"), except that since this position also occupies
the same 16 bits as the CCF_MARK_DIRTY flag, you need to shift this
position by an offset, which is pre-defined as CCF_REFERENCE_OFFSET.
The above point shows up in the docs, in the Objects book, in Sec 2.5.2,
"Manipulating Children Directly," under the CCF_REFERENCE paragraph,
right after the typo you mentioned above:
"For example, a CCF_REFERENCE value of five would specify
the fourth child of the parent obejct, or the last child
if there are fewer than five children currently. When
specifying a position for CCF_REFERENCE, use the
CCF_REFERENCE_OFFSET (using the shift operator)."
One last note: you'll notice that CCF_REFERENCE_OFFSET is actually
defined as 0 -- so leaving it off, at this point, makes no difference.
It is, however, good programming style to include it, in case it
changes someday in GEOS: your compiled code would still run correctly,
then.
SO : to sum up, your last line should correctly look like this:
@call parent::MSG_GEN_ADD_CHILD(newchild,
(CCF_MARK_DIRTY |
(position << CCF_REFERENCE_OFFSET)) );
Hope this helps.
Happy Holidays!
Best regards,
Paul.