Code

added fix from Dale Harvey to expand incomplete JIDs specified in user
[inkscape.git] / src / libnr / nr-object.cpp
1 #define __NR_OBJECT_C__
3 /*
4  * RGBA display list system for inkscape
5  *
6  * Authors:
7  *   Lauris Kaplinski <lauris@kaplinski.com>
8  *   MenTaLguY <mental@rydia.net>
9  *
10  * This code is in public domain
11  */
13 #include <string.h>
14 #include <stdio.h>
16 #include <libnr/nr-macros.h>
18 #include "nr-object.h"
20 unsigned int nr_emit_fail_warning(const gchar *file, unsigned int line, const gchar *method, const gchar *expr)
21 {
22     fprintf (stderr, "File %s line %d (%s): Assertion %s failed\n", file, line, method, expr);
23     return 1;
24 }
26 /* NRObject */
28 static NRObjectClass **classes = NULL;
29 static unsigned int classes_len = 0;
30 static unsigned int classes_size = 0;
32 NRType nr_type_is_a(NRType type, NRType test)
33 {
34     nr_return_val_if_fail(type < classes_len, FALSE);
35     nr_return_val_if_fail(test < classes_len, FALSE);
37     NRObjectClass *c = classes[type];
39     while (c) {
40         if (c->type == test) {
41             return TRUE;
42         }
43         c = c->parent;
44     }
46     return FALSE;
47 }
49 void const *nr_object_check_instance_cast(void const *ip, NRType tc)
50 {
51     nr_return_val_if_fail(ip != NULL, NULL);
52     nr_return_val_if_fail(nr_type_is_a(((NRObject const *) ip)->klass->type, tc), ip);
53     return ip;
54 }
56 unsigned int nr_object_check_instance_type(void const *ip, NRType tc)
57 {
58     if (ip == NULL) {
59         return FALSE;
60     }
61     
62     return nr_type_is_a(((NRObject const *) ip)->klass->type, tc);
63 }
65 NRType nr_object_register_type(NRType parent,
66                                gchar const *name,
67                                unsigned int csize,
68                                unsigned int isize,
69                                void (* cinit) (NRObjectClass *),
70                                void (* iinit) (NRObject *))
71 {
72     if (classes_len >= classes_size) {
73         classes_size += 32;
74         classes = nr_renew (classes, NRObjectClass *, classes_size);
75         if (classes_len == 0) {
76             classes[0] = NULL;
77             classes_len = 1;
78         }
79     }
81     NRType const type = classes_len;
82     classes_len += 1;
84     classes[type] = (NRObjectClass*) new char[csize];
85     NRObjectClass *c = classes[type];
87     /* FIXME: is this necessary? */
88     memset(c, 0, csize);
90     if (classes[parent]) {
91         memcpy(c, classes[parent], classes[parent]->csize);
92     }
94     c->type = type;
95     c->parent = classes[parent];
96     c->name = strdup(name);
97     c->csize = csize;
98     c->isize = isize;
99     c->cinit = cinit;
100     c->iinit = iinit;
101     
102     c->cinit(c);
103     
104     return type;
107 static void nr_object_class_init (NRObjectClass *klass);
108 static void nr_object_init (NRObject *object);
109 static void nr_object_finalize (NRObject *object);
111 NRType nr_object_get_type()
113     static NRType type = 0;
115     if (!type) {
116         type = nr_object_register_type (0,
117                                         "NRObject",
118                                         sizeof (NRObjectClass),
119                                         sizeof (NRObject),
120                                         (void (*) (NRObjectClass *)) nr_object_class_init,
121                                         (void (*) (NRObject *)) nr_object_init);
122     }
123     
124     return type;
127 static void nr_object_class_init(NRObjectClass *c)
129     c->finalize = nr_object_finalize;
130     c->cpp_ctor = NRObject::invoke_ctor<NRObject>;
133 static void nr_object_init (NRObject *object)
137 static void nr_object_finalize (NRObject *object)
141 /* Dynamic lifecycle */
143 static void nr_class_tree_object_invoke_init(NRObjectClass *c, NRObject *object)
145     if (c->parent) {
146         nr_class_tree_object_invoke_init(c->parent, object);
147     }
148     c->iinit (object);
151 namespace {
153 void finalize_object(void *base, void *)
155     NRObject *object = reinterpret_cast<NRObject *>(base);
156     object->klass->finalize(object);
157     object->~NRObject();
162 NRObject *NRObject::alloc(NRType type)
164     nr_return_val_if_fail (type < classes_len, NULL);
166     NRObjectClass *c = classes[type];
168     if ( c->parent && c->cpp_ctor == c->parent->cpp_ctor ) {
169         g_error("Cannot instantiate NRObject class %s which has not registered a C++ constructor\n", c->name);
170     }
172     NRObject *object = reinterpret_cast<NRObject *>(
173         ::operator new(c->isize, Inkscape::GC::SCANNED, Inkscape::GC::AUTO,
174                        &finalize_object, NULL)
175     );
176     memset(object, 0xf0, c->isize);
178     object->klass = c;
179     c->cpp_ctor(object);
180     nr_class_tree_object_invoke_init (c, object);
182     return object;
185 /* NRActiveObject */
187 static void nr_active_object_class_init(NRActiveObjectClass *c);
188 static void nr_active_object_init(NRActiveObject *object);
189 static void nr_active_object_finalize(NRObject *object);
191 static NRObjectClass *parent_class;
193 NRType nr_active_object_get_type()
195     static NRType type = 0;
196     if (!type) {
197         type = nr_object_register_type (NR_TYPE_OBJECT,
198                                         "NRActiveObject",
199                                         sizeof (NRActiveObjectClass),
200                                         sizeof (NRActiveObject),
201                                         (void (*) (NRObjectClass *)) nr_active_object_class_init,
202                                         (void (*) (NRObject *)) nr_active_object_init);
203     }
204     return type;
207 static void nr_active_object_class_init(NRActiveObjectClass *c)
209     NRObjectClass *object_class = (NRObjectClass *) c;
211     parent_class = object_class->parent;
213     object_class->finalize = nr_active_object_finalize;
214     object_class->cpp_ctor = NRObject::invoke_ctor<NRActiveObject>;
217 static void nr_active_object_init(NRActiveObject *object)
221 static void nr_active_object_finalize(NRObject *object)
223     NRActiveObject *aobject = (NRActiveObject *) object;
225     if (aobject->callbacks) {
226         for (unsigned int i = 0; i < aobject->callbacks->length; i++) {
227             NRObjectListener *listener = aobject->callbacks->listeners + i;
228             if ( listener->vector->dispose ) {
229                 listener->vector->dispose(object, listener->data);
230             }
231         }
232         free (aobject->callbacks);
233     }
235     ((NRObjectClass *) (parent_class))->finalize(object);
238 void nr_active_object_add_listener(NRActiveObject *object,
239                                    const NRObjectEventVector *vector,
240                                    unsigned int size,
241                                    void *data)
243     if (!object->callbacks) {
244         object->callbacks = (NRObjectCallbackBlock*) malloc(sizeof(NRObjectCallbackBlock));
245         object->callbacks->size = 1;
246         object->callbacks->length = 0;
247     }
248     
249     if (object->callbacks->length >= object->callbacks->size) {
250         int newsize = object->callbacks->size << 1;
251         object->callbacks = (NRObjectCallbackBlock *)
252             realloc(object->callbacks, sizeof(NRObjectCallbackBlock) + (newsize - 1) * sizeof (NRObjectListener));
253         object->callbacks->size = newsize;
254     }
255     
256     NRObjectListener *listener = object->callbacks->listeners + object->callbacks->length;
257     listener->vector = vector;
258     listener->size = size;
259     listener->data = data;
260     object->callbacks->length += 1;
263 void nr_active_object_remove_listener_by_data(NRActiveObject *object, void *data)
265     if (object->callbacks == NULL) {
266         return;
267     }
268     
269     for (unsigned i = 0; i < object->callbacks->length; i++) {
270         NRObjectListener *listener = object->callbacks->listeners + i;
271         if ( listener->data == data ) {
272             object->callbacks->length -= 1;
273             if ( object->callbacks->length < 1 ) {
274                 free(object->callbacks);
275                 object->callbacks = NULL;
276             } else if ( object->callbacks->length != i ) {
277                 *listener = object->callbacks->listeners[object->callbacks->length];
278             }
279             return;
280         }
281     }
286 /*
287   Local Variables:
288   mode:c++
289   c-file-style:"stroustrup"
290   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
291   indent-tabs-mode:nil
292   fill-column:99
293   End:
294 */
295 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :