convert line ends
[canaan.git] / prj / cam / src / object / relinver.cpp
blob71ec9e859889a2000c691deef2be97f29bab1430
1 /*
2 @Copyright Looking Glass Studios, Inc.
3 1996,1997,1998,1999,2000 Unpublished Work.
4 */
6 // $Header: r:/t2repos/thief2/src/object/relinver.cpp,v 1.10 1998/10/19 13:04:49 mahk Exp $
7 #include <linkbase.h>
8 #include <relinver.h>
9 #include <lnkquery.h>
10 #include <string.h>
11 #include <linkid.h>
13 #include <dlist.h>
14 #include <dlisttem.h>
16 // Must be last header
17 #include <dbmem.h>
19 cInverseRelation::cInverseRelation(IRelation* rel)
20 : Relation(rel)
22 rel->AddRef();
24 // build the descriptor
25 const sRelationDesc* desc = rel->Describe();
26 Desc = *desc;
27 strcpy(Desc.name,RELNAME_INVERSE_PREFIX);
28 strncat(Desc.name,desc->name,sizeof(Desc.name)-strlen(Desc.name)-1);
32 cInverseRelation::~cInverseRelation()
34 SafeRelease(Relation);
37 STDMETHODIMP_(const sRelationDesc*) cInverseRelation::Describe() const
39 return &Desc;
42 ////////////////////////////////////////
44 STDMETHODIMP_(RelationID) cInverseRelation::GetID() const
46 return RELID_INVERT(Relation->GetID());
49 ////////////////////////////////////////
51 STDMETHODIMP cInverseRelation::SetID(RelationID id)
53 Warning(("Someone is calling cInverseRelation::SetID()!\n"));
54 return Relation->SetID(RELID_INVERT(id));
58 ////////////////////////////////////////
60 STDMETHODIMP_(const sRelationDataDesc*) cInverseRelation::DescribeData() const
62 return Relation->DescribeData();
65 ////////////////////////////////////////
67 STDMETHODIMP_(IRelation*) cInverseRelation::Inverse()
69 Relation->AddRef();
70 return Relation;
73 ////////////////////////////////////////
75 STDMETHODIMP_(LinkID) cInverseRelation::Add(ObjID source, ObjID dest)
77 LinkID id = Relation->Add(dest,source);
78 return LINKID_INVERT(id);
81 STDMETHODIMP_(LinkID) cInverseRelation::AddFull(ObjID s, ObjID d, void* dat)
83 LinkID id = Relation->AddFull(d,s,dat);
84 return LINKID_INVERT(id);
87 ////////////////////////////////////////
89 STDMETHODIMP cInverseRelation::Remove(LinkID link)
91 return Relation->Remove(LINKID_INVERT(link));
95 static void invert_slink(sLink* link)
97 ObjID tmp = link->source;
98 link->source = link->dest;
99 link->dest = tmp;
100 link->flavor = RELID_INVERT(link->flavor);
103 STDMETHODIMP_(BOOL) cInverseRelation::Get(LinkID id, sLink* link) const
105 if (Relation->Get(LINKID_INVERT(id),link))
107 invert_slink(link);
108 return TRUE;
110 return FALSE;
113 STDMETHODIMP cInverseRelation::SetData(LinkID id, void* data)
115 return Relation->SetData(LINKID_INVERT(id),data);
118 void* cInverseRelation::GetData(LinkID id)
120 return Relation->GetData(LINKID_INVERT(id));
123 ////////////////////////////////////////
125 // Nothing better to do here than hand off to the real relation
126 STDMETHODIMP cInverseRelation::Notify(eRelationNotifyMsg msg, RelationNotifyData data)
128 return Relation->Notify(msg,data);
131 ////////////////////////////////////////
133 struct sListenerData
135 RelationListenFunc func;
136 RelationListenerData data;
140 void LGAPI cInverseRelation::Listener(sRelationListenMsg* msg_, RelationListenerData data)
142 sRelationListenMsg msg = *msg_;
143 sListenerData* listen = (sListenerData*)data;
144 // invert the message
145 msg.id = LINKID_INVERT(msg.id);
146 invert_slink(&msg.link);
148 listen->func(&msg,listen->data);
151 // Just a list of listeners so that they get cleaned up at the end of time
152 // If we add unlisten, each elem is going to need a relation/handle id.
154 static cSimpleDList<sListenerData> gListeners;
156 STDMETHODIMP cInverseRelation::Listen(RelationListenMsgSet msgs, RelationListenFunc func , RelationListenerData data)
158 sListenerData listener = { func, data };
159 // add the listener to our list
160 gListeners.Append(listener);
162 // Get the actual copy that's in our list
163 sListenerData* our_data = &gListeners.GetLast()->Value();
165 // add our listener
166 return Relation->Listen(msgs,Listener,our_data);
169 ////////////////////////////////////////
171 STDMETHODIMP_(LinkID) cInverseRelation::GetSingleLink(ObjID source, ObjID dest)
173 return Relation->GetSingleLink(dest, source);
176 ////////////////////////////////////////
178 STDMETHODIMP_(BOOL) cInverseRelation::AnyLinks(ObjID source, ObjID dest)
180 return Relation->AnyLinks(dest, source);
183 ////////////////////////////////////////////////////////////
185 // cInverseQuery
187 // Take a query and invert it.
188 ////////////////////////////////////////////////////////////
191 class cInverseQuery : public ILinkQuery
193 ILinkQuery* Query;
194 public:
195 DECLARE_UNAGGREGATABLE();
197 cInverseQuery(ILinkQuery* q) :Query(q) { Query->AddRef();};
198 virtual ~cInverseQuery() { SafeRelease(Query);};
201 STDMETHOD_(BOOL,Done)() const;
202 STDMETHOD(Link)(sLink* link) const;
203 STDMETHOD(Next)();
205 STDMETHOD_(LinkID,ID)() const
207 LinkID id = Query->ID();
208 return LINKID_INVERT(id);
210 STDMETHOD_(void*,Data)() const { return Query->Data();};
212 STDMETHOD_(ILinkQuery*,Inverse)()
214 Query->AddRef();
215 return Query;
220 IMPLEMENT_UNAGGREGATABLE_SELF_DELETE(cInverseQuery,ILinkQuery);
223 STDMETHODIMP_(BOOL) cInverseQuery::Done() const
225 return Query->Done();
228 STDMETHODIMP cInverseQuery::Link(sLink* link) const
230 HRESULT result = Query->Link(link);
231 if (FAILED(result)) return result;
232 invert_slink(link);
233 return result;
236 STDMETHODIMP cInverseQuery::Next()
238 return Query->Next();
241 ////////////////////////////////////////
243 STDMETHODIMP_(ILinkQuery*) cInverseRelation::Query(ObjID s, ObjID d) const
245 ILinkQuery* q = Relation->Query(d,s);
246 ILinkQuery* retval = q->Inverse();
247 SafeRelease(q);
248 return retval;
251 ////////////////////////////////////////
253 ILinkQuery* CreateInverseLinkQuery(ILinkQuery* q)
255 return new cInverseQuery(q);