Moderators .. please re-enable .INC file extension :)

;This is a BaseClass which implements a Node Hierarchy.
;No support for inserting or unlinking objects.
;Don't use the AppendSibling method unless you are seriously demented.
;It's a PRIVATE METHOD meant only to be called by AddChild method.
;As such, I have removed it from the Class Definition, so it won't waste space
;appearing in the vtable of object instances.

;AddChild ;Adds given object as Child of THIS object
;If THIS.Child exists, then (icall this.AppendSibling, pNewObject)
;Else, add as THIS.Child == given object

;AppendSibling ; Don't call this yourself - it's called by AddChild.
; Adds given object as a Sibling of the Child of THIS object.
; Should only be called where THIS.Child exists (of course).
; If THIS.Child.LastSibling exists, then add as YoungerSibling of THIS.Child.LastSibling
; Else, add as THIS.Child.YoungerSibling == given object
; Either Way, set THIS.Child.LastSibling == given object

class TreeNode, ,C++ compatible
void AddChild:pNewChild ;Links a new object to the Tree, somewhere "below" THIS object (read notes)
void DelTree ;Deletes THIS object, plus anything "below" it in the Tree Hierarchy
void SetName:pName
long pParent ;Pointer to the previous node
long pChild ;Pointer to the next node
long pOlderSibling
long pYoungerSibling
long pLastSibling
long pName
long dwChildren ;<--#Children owned by THIS object (Child+#Siblings)
long dwNodeType

TreeNode_TreeNode proc
xor eax,eax
mov [ecx].TreeNode.dwChildren,eax
mov [ecx].TreeNode.pParent,eax
mov [ecx].TreeNode.pChild ,eax
mov [ecx].TreeNode.pOlderSibling,eax
mov [ecx].TreeNode.pYoungerSibling,eax
mov [ecx].TreeNode.pLastSibling, eax
mov [ecx].TreeNode.pName, eax
mov [ecx].TreeNode.dwNodeType, eax
TreeNode_TreeNode endp

TreeNode_SetName proc pName
invoke AllocString, pName ;<-- allocates heapmem for namestring, copies string into it, returns ptr
mov [ecx].TreeNode.pName,eax
TreeNode_SetName endp

TreeNode_$TreeNode proc
.if [ecx].TreeNode.pName!=NULL
free [ecx].TreeNode.pName
.if [ecx].TreeNode.pParent!=NULL
mov ebx,[ecx].TreeNode.pParent
dec [ebx].TreeNode.dwChildren
TreeNode_$TreeNode endp

TreeNode_AppendSibling proc pNewSibling
mov ebx, [ecx].TreeNode.pChild ;<--ebx=ptr to my child
mov eax, [ebx].TreeNode.pLastSibling ;<--eax=ptr to my child's LastSibling
mov ecx,pNewSibling
.if eax==NULL ;If my child has no Siblings yet
mov [ebx].TreeNode.pYoungerSibling, ecx ;Noting that we leave OlderSibling of my child NULLed
Message "Added node as First Sibling of Child"
.else ;But if we have one or more Siblings already
mov [eax].TreeNode.pYoungerSibling, ecx ;<-- write new object to end of sibs
mov [ecx].TreeNode.pOlderSibling, eax ;<-- inform new object of its older sib
Message "Added node as Last Sibling of Child"
mov [ebx].TreeNode.pLastSibling, ecx ;<-- set Parent.Child of new last sib
TreeNode_AppendSibling endp

TreeNode_AddChild proc pNewChild
mov ebx,pNewChild
mov [ebx].TreeNode.pParent, ecx
.if [ecx].TreeNode.pChild!=NULL ;If there's already atleast one child
; icall ecx, TreeNode, AppendSibling, pNewChild ;Add Child to Parent.Child (or end of its sibs)
push ecx
invoke TreeNode_AppendSibling, pNewChild ;<-- *** CALL PRIVATE METHOD AS PROC ***
.else ;Otherwise if theres no children at all
mov [ecx].TreeNode.pChild, ebx ;Add Child to Parent
Message "Added node as First Child"
inc [ecx].TreeNode.dwChildren
TreeNode_AddChild endp

TreeNode_DelTree proc
.if [ecx].TreeNode.pYoungerSibling!=NULL
icall [ecx].TreeNode.pYoungerSibling, TreeNode, DelTree;<-- walk the Sibling chain (call self on Sibling)
.if [ecx].TreeNode.pChild!=NULL
icall [ecx].TreeNode.pChild, TreeNode, DelTree ;<-- walk the Child chain (call self on Child)
delete ecx ;<-- delete THIS object
TreeNode_DelTree endp

Posted on 2004-10-09 01:57:15 by Homer

;This class implements a SwitchNode.
;This Node, like all Nodes, derives from the TreeNode baseclass.
;The job of this Node is to act as a fork in the road,
;by maintaining an Active Child from among its Children (or elsewhere!)
;which can be changed anytime (for example by another Node).
;This causes the Tree Walker to walk the path we choose at runtime.
class SwitchNode,TreeNode,C++ compatible
virtual GetTreePath
virtual SetTreePath:pNewActiveChild
long pActiveChild
SwitchNode_SwitchNode proc
xor eax,eax
mov [ecx].SwitchNode.pActiveChild, eax
mov [ecx].SwitchNode.dwNodeType, NODETYPE_SWITCH
SwitchNode_SwitchNode endp
SwitchNode_$SwitchNode proc
SwitchNode_$SwitchNode endp
SwitchNode_SetTreePath proc pNewActiveChild
m2m [ecx].SwitchNode.pActiveChild, pNewActiveChild
SwitchNode_SetTreePath endp
SwitchNode_GetTreePath proc
return [ecx].SwitchNode.pActiveChild
SwitchNode_GetTreePath endp

Posted on 2004-10-09 01:58:24 by Homer

TreeNode_WalkTree proc
$Message "CurrentNode=%s",[ecx].TreeNode.pName
.if [ecx].TreeNode.pChild!=0 ;Try to walk Child of current node
icall [ecx].TreeNode.pChild, TreeNode, WalkTree
.if [ecx].TreeNode.pYoungerSibling!=0 ;Try to walk Siblings of current node
icall [ecx].TreeNode.pYoungerSibling, TreeNode, WalkTree
TreeNode_WalkTree endp
Posted on 2004-10-09 13:47:21 by Homer