2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these libraries and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
24 * $XConsortium: FolioObject.C /main/5 1996/10/04 11:23:44 drk $
26 * Copyright (c) 1992 HaL Computer Systems, Inc. All rights reserved.
27 * UNPUBLISHED -- rights reserved under the Copyright Laws of the United
28 * States. Use of a copyright notice is precautionary only and does not
29 * imply publication or disclosure.
31 * This software contains confidential information and trade secrets of HaL
32 * Computer Systems, Inc. Use, disclosure, or reproduction is prohibited
33 * without the prior express written permission of HaL Computer Systems, Inc.
35 * RESTRICTED RIGHTS LEGEND
36 * Use, duplication, or disclosure by the Government is subject to
37 * restrictions as set forth in subparagraph (c)(l)(ii) of the Rights in
38 * Technical Data and Computer Software clause at DFARS 252.227-7013.
39 * HaL Computer Systems, Inc.
40 * 1315 Dell Avenue, Campbell, CA 95008
48 INIT_CLASS (FolioObject);
50 // private class to hold dependent data
51 // NOTE: To avoid overhead there should be a class below FolioObject
52 // to hold the dependency type stuff called "??"
53 // Need to fix this up later.
54 // BaseObject -> Object -> Hasbable -> etc.
55 // This may not be a problem once we have templates, because then we can
56 // stick anything in our list.
61 Dependent (Dependent **pre_next, Dependent *next,
62 FolioObject *dependent, FolioObject *folio_object,
63 notify_handler_t handler,
64 u_int notify_type, void *dependent_data)
65 : f_pre_next (pre_next), f_next (next),
66 f_dependent (dependent), f_folio_object (folio_object),
68 f_notify_type (notify_type), f_dependent_data (dependent_data)
69 { if (next) next->f_pre_next = &f_next; }
70 Dependent **f_pre_next;
72 FolioObject *f_dependent;
73 FolioObject *f_folio_object;
74 notify_handler_t f_handler;
76 void *f_dependent_data;
78 void call (FolioObject *obj, void *notify_data);
84 ON_DEBUG(printf ("@** assigning: f_dependent = %p\n", f_next));
86 if (f_next) f_next->f_pre_next = f_pre_next;
91 Dependent::call (FolioObject *obj, void *notify_data)
93 (f_dependent->*f_handler)(obj, f_notify_type, notify_data, f_dependent_data);
100 DependOnList (DependOnList *next, Dependent *d)
101 : f_next (next), f_dependent_obj (d)
103 void delete_dependent();
104 DependOnList *f_next;
105 Dependent *f_dependent_obj;
109 DependOnList::delete_dependent()
111 f_dependent_obj->release();
115 // /////////////////////////////////////////////////////////////////
117 // /////////////////////////////////////////////////////////////////
119 FolioObject::FolioObject()
120 : f_dependents (NULL), f_depend_on_list (NULL)
122 // Initialize status to reasonable value.
123 // Subclasses only need to change on creation if an error occurs.
124 setStatus (eSuccess);
125 f_initialized = FALSE;
129 // /////////////////////////////////////////////////////////////////
131 // /////////////////////////////////////////////////////////////////
133 FolioObject::~FolioObject()
136 release_dependents();
137 release_depend_on_list();
141 // /////////////////////////////////////////////////////////////////
142 // notify - this object changed
143 // /////////////////////////////////////////////////////////////////
146 FolioObject::notify (u_int notify_type, void *notify_data)
150 // NOTE: This function is temporarily hacked up to get the next
151 // entry in the list before calling the function because it
152 // might be a destroy message which causes the object notified
153 // to destroy itself and delete the current Dependent object,
154 // leaving d pointing into freed memory. next could also point
155 // into freed memory, so for now we need to make sure that any
156 // notification that deletes the target object is at the end
157 // of the list of dependents. This is done by adding first, since
158 // Dependent records are added to the start of the list.
159 // The Right fix for this is probably to pull items from the "to check"
160 // list and move them to a "called" list as they are called. After
161 // each call, d should start at the beginning of the "to check" list
162 // since it will be the only memory guaranteed to be around.
164 for (d = f_dependents; d != NULL;)
167 if (d->f_notify_type == notify_type)
168 d->call (this, notify_data);
174 // /////////////////////////////////////////////////////////////////
175 // add_dependent - add a new dependent
176 // /////////////////////////////////////////////////////////////////
179 #if defined(SC3) || defined(__SunOS)
180 FolioObject::add_dependent (FolioObject *dependent, notify_handler_t handler,
182 FolioObject::add_dependent (void *dependent, notify_handler_t handler,
184 u_int notify_type, void *dependent_data)
186 // Adds to begining because that's easiest.
187 #if defined(SC3) || defined(__SunOS)
188 f_dependents = new Dependent (&f_dependents, f_dependents,
189 dependent, NULL, handler,
190 notify_type, dependent_data);
192 f_dependents = new Dependent (&f_dependents, f_dependents,
193 (FolioObject*)dependent, NULL, handler,
194 notify_type, dependent_data);
196 ON_DEBUG(printf ("@@@2 adding dependent %p to object %p\n",
197 f_dependents, this));
198 // Also remember it in the dependent for easy removal if it is deleted.
199 // The code below failed in a big way because the "dependent" variable
200 // was the real this pointer of the original object, not the offset
201 // this pointer for a FolioObject (in a multiply inherited object).
202 // The net result was the the code mucked up the object because dependent
203 // really wasn't a FolioObject.
204 // NOTE: need to change all code in which we're doing semi-bogus stuff
205 // with a FolioObject to be a void * so that functions can't be called
206 // by mistake like this. We'll just have to cast it to a FolioObject
207 // when the call through it is made and hope the compiler doesn't
208 // expect it to point to an actual FolioObject (or whatever, eg: WWL).
209 #if defined(SC3) || defined(__SunOS)
210 ON_DEBUG(printf ("@@@ adding to depend_on_list of %p\n", dependent));
211 dependent->f_depend_on_list =
212 new DependOnList (dependent->f_depend_on_list, f_dependents);
217 // /////////////////////////////////////////////////////////////////
219 // /////////////////////////////////////////////////////////////////
222 FolioObject::remove_depend_on (FolioObject *target, Dependent *d)
224 ON_DEBUG(printf ("Calling remove_depend_on for object %p, entry %p\n",
227 for (l = &(target->f_depend_on_list); *l != NULL; l = &((*l)->f_next))
229 ON_DEBUG(printf (" checking against entry %p\n", *l));
230 if ((*l)->f_dependent_obj == d)
232 ON_DEBUG(printf ("removing DependOnList %p\n", *l));
233 DependOnList *dead_meat = *l;
242 // /////////////////////////////////////////////////////////////////
243 // remove_dependent - remove first matching dependent
244 // /////////////////////////////////////////////////////////////////
247 #if defined(SC3) || defined(__SunOS)
248 FolioObject::remove_dependent (FolioObject *dependent,
250 FolioObject::remove_dependent (void *dependent,
252 notify_handler_t handler,
253 u_int notify_type, void *dependent_data)
257 // This only removes the first matching handler!
258 // That means that each handler added must be removed!
259 for (d = &f_dependents; *d != NULL; d = &((*d)->f_next))
261 #if defined(SC3) || defined(__SunOS)
262 if ((*d)->f_dependent == dependent &&
264 if ((*d)->f_dependent == (FolioObject*)dependent &&
266 (*d)->f_handler == handler &&
267 (*d)->f_notify_type == notify_type &&
268 (*d)->f_dependent_data == dependent_data)
270 // Following line is BOGUS because dependent is "real this"
271 // not necessarily a FolioObject!
272 // f_folio_object will be NULL if the Dependent object was
273 // created in add_dependent! DJB 11/10/92
274 assert ((*d)->f_folio_object != NULL);
275 #if defined(SC3) || defined(__SunOS)
276 remove_depend_on (dependent, *d);
278 remove_depend_on ((FolioObject*)dependent, *d);
280 Dependent *dead_meat = *d;
289 // /////////////////////////////////////////////////////////////////
290 // release_dependents - free all dependents
291 // /////////////////////////////////////////////////////////////////
294 FolioObject::release_dependents()
296 Dependent *d = f_dependents, *next;
300 // NOTE: Quick fix below. Improve with doubly-linked lists and
301 // cross pointers in Dependent and DependOnList objects.
302 // f_folio_object member is part of the quick fix. DJB 11/10/92
303 if (d->f_folio_object != NULL)
304 remove_depend_on (d->f_folio_object, d);
306 ON_DEBUG(printf ("WARNING: NULL f_folio_object member in release_dependents\n"));
315 // /////////////////////////////////////////////////////////////////
316 // release_depend_on_list
317 // /////////////////////////////////////////////////////////////////
320 FolioObject::release_depend_on_list()
322 DependOnList *l = f_depend_on_list, *next;
327 l->delete_dependent();
332 f_depend_on_list = NULL;
336 // /////////////////////////////////////////////////////////////////
337 // select_on - alternative add_dependent interface
338 // /////////////////////////////////////////////////////////////////
340 // NOTE: it would be useful to have this call return a handle to
341 // the thing we're observing so that we can stop observing just
342 // by deleting that handle!!!
345 #if defined(SC3) || defined(__SunOS)
346 FolioObject::observe (FolioObject *real_this, FolioObject *target,
348 FolioObject::observe (void *real_this, FolioObject *target,
350 notify_handler_t handler, u_int notify_type,
351 void *dependent_data)
353 // This routine will not work, because if target multiply inherits
354 // from FolioObject (like Agent) and FolioObject is not first inherited
355 // class, the this pointer in this routine will be offset from the
356 // real object this pointer, which will cause big problems when
357 // we try to call the callback which expects the real this pointer.
359 // OK, instead we will have to pass in the "real" this pointer which
360 // may be different from the this pointer visible in this routine.
361 #if defined(SC3) || defined(__SunOS)
362 target->f_dependents =
363 new Dependent (&target->f_dependents, target->f_dependents,
365 handler, notify_type, dependent_data);
366 assert( real_this == this );
368 target->f_dependents =
369 new Dependent (&target->f_dependents, target->f_dependents,
370 (FolioObject *) real_this, this,
371 handler, notify_type, dependent_data);
373 ON_DEBUG(printf ("@@@ adding dependent %p to object %p for object %p\n",
374 target->f_dependents, target, this));
376 new DependOnList (f_depend_on_list, target->f_dependents);
380 FolioObject::display_as()
382 return "Generic Folio Object";