* lib/text.h: Added text_get_line() declaration
[dia.git] / lib / prop_basic.c
blobf8e11b2ed6d4327bb5cdfadd500a32555d1dd7bc
1 /* Dia -- a diagram creation/manipulation program -*- c -*-
2 * Copyright (C) 1998 Alexander Larsson
4 * Property system for dia objects/shapes.
5 * Copyright (C) 2000 James Henstridge
6 * Copyright (C) 2001 Cyrille Chepelov
7 * Major restructuration done in August 2001 by C. Chepelov
9 * Basic Property types definition.
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 #ifdef HAVE_CONFIG_H
27 #include <config.h>
28 #endif
30 #include <string.h>
32 #include <gtk/gtk.h>
33 #define WIDGET GtkWidget
34 #include "properties.h"
35 #include "prop_basic.h"
36 #include "propinternals.h"
38 typedef struct {
39 const gchar *name;
40 const gchar *type;
41 } PropMoniker;
43 static guint
44 desc_hash_hash(const PropMoniker *desc)
46 guint name_hash = g_str_hash(desc->name);
47 guint type_hash = g_str_hash(desc->type);
49 return (name_hash ^ ((type_hash & 0xFFFF0000) >> 16) ^
50 ((type_hash & 0x0000FFFF) << 16) ^ (type_hash));
53 static guint
54 desc_hash_compare(const PropMoniker *a, const PropMoniker *b)
56 return ((0 == strcmp(a->name,b->name)) && (0 == strcmp(a->type,b->type)));
59 Property *
60 make_new_prop(const char *name, PropertyType type, guint flags)
62 static GHashTable *hash = NULL;
63 PropMoniker *moniker = g_new0(PropMoniker, 1);
64 PropDescription *descr;
66 moniker->name = name;
67 moniker->type = type;
69 if (!hash) hash = g_hash_table_new((GHashFunc)desc_hash_hash,
70 (GCompareFunc)desc_hash_compare);
72 descr = g_hash_table_lookup(hash,moniker);
73 if (descr) {
74 g_free(moniker);
75 } else {
76 descr = g_new0(PropDescription,1);
77 descr->name = name;
78 descr->type = type;
79 descr->flags = flags;
80 descr->quark = g_quark_from_static_string(descr->name);
81 descr->type_quark = g_quark_from_static_string(descr->type);
82 descr->ops = prop_type_get_ops(type);
83 g_hash_table_insert(hash,moniker,descr);
84 /* we don't ever free anything allocated here. */
86 return descr->ops->new_prop(descr,pdtpp_synthetic);
90 /**************************************************************************/
91 /* The COMMON property type. prop->ops will always point to these ops, */
92 /* whose role is to update the prop->experience flag field and then call */
93 /* the original property routines. Exception is commonprop_new which does */
94 /* not exist. */
95 /**************************************************************************/
97 static Property *
98 commonprop_new(const PropDescription *pdesc, PropDescToPropPredicate reason)
100 /* Will be called mostly when doing copies and empty copies.
101 Will NOT be called upon the creation of an original property. */
102 return pdesc->ops->new_prop(pdesc,reason);
105 static void
106 commonprop_free(Property *prop)
108 prop->real_ops->free(prop);
111 static Property *
112 commonprop_copy(Property *src)
114 Property *prop = src->real_ops->copy(src);
115 src->experience |= PXP_COPIED;
116 prop->experience |= PXP_COPY;
117 return prop;
120 static WIDGET *
121 commonprop_get_widget(Property *prop, PropDialog *dialog)
123 WIDGET *wid = prop->real_ops->get_widget(prop,dialog);
124 prop->experience |= PXP_GET_WIDGET;
125 return wid;
128 static void
129 commonprop_reset_widget(Property *prop, WIDGET *widget)
131 prop->real_ops->reset_widget(prop,widget);
132 prop->experience |= PXP_RESET_WIDGET;
135 static void
136 commonprop_set_from_widget(Property *prop, WIDGET *widget)
138 prop->real_ops->set_from_widget(prop,widget);
139 prop->experience |= PXP_SET_FROM_WIDGET;
142 static void
143 commonprop_load(Property *prop, AttributeNode attr, DataNode data)
145 prop->real_ops->load(prop,attr,data);
146 prop->experience |= PXP_LOADED;
149 static void
150 commonprop_save(Property *prop, AttributeNode attr)
152 prop->real_ops->save(prop,attr);
153 prop->experience |= PXP_SAVED;
156 static gboolean
157 commonprop_can_merge(const PropDescription *pd1, const PropDescription *pd2)
159 return pd1->ops->can_merge(pd1,pd2);
162 static void
163 commonprop_get_from_offset(const Property *prop,
164 void *base, guint offset, guint offset2)
166 prop->real_ops->get_from_offset(prop,base,offset,offset2);
167 ((Property *)prop)->experience |= PXP_GFO;
170 static void
171 commonprop_set_from_offset(Property *prop,
172 void *base, guint offset, guint offset2)
174 prop->real_ops->set_from_offset(prop,base,offset,offset2);
175 prop->experience |= PXP_SFO;
178 static const PropertyOps commonprop_ops = {
179 (PropertyType_New) commonprop_new,
180 (PropertyType_Free) commonprop_free,
181 (PropertyType_Copy) commonprop_copy,
182 (PropertyType_Load) commonprop_load,
183 (PropertyType_Save) commonprop_save,
184 (PropertyType_GetWidget) commonprop_get_widget,
185 (PropertyType_ResetWidget) commonprop_reset_widget,
186 (PropertyType_SetFromWidget) commonprop_set_from_widget,
188 (PropertyType_CanMerge) commonprop_can_merge,
189 (PropertyType_GetFromOffset) commonprop_get_from_offset,
190 (PropertyType_SetFromOffset) commonprop_set_from_offset
195 void initialize_property(Property *prop, const PropDescription *pdesc,
196 PropDescToPropPredicate reason)
198 prop->reason = reason;
199 prop->name = pdesc->name;
200 prop->name_quark = pdesc->quark;
201 if (!prop->name_quark) {
202 prop->name_quark = g_quark_from_string(prop->name);
203 g_error(G_GNUC_FUNCTION ": late quark construction for property %s",
204 prop->name);
206 prop->type = pdesc->type;
207 prop->type_quark = pdesc->type_quark;
208 prop->ops = &commonprop_ops;
209 prop->real_ops = pdesc->ops;
210 /* if late quark construction, we'll have NULL here */
211 prop->descr = pdesc;
212 prop->reason = reason;
213 prop->extra_data = pdesc->extra_data;
214 /* prop->self remains 0 until we get a widget from this. */
215 prop->event_handler = pdesc->event_handler;
217 prop->experience = 0;
220 void copy_init_property(Property *dest, const Property *src)
221 { /* XXX: inline this ? */
222 memcpy(dest,src,sizeof(*dest));
223 dest->experience = 0;
227 /**************************************************************************/
228 /* The NOOP property type. It is mostly useful to serve as both a library */
229 /* and a cut-n-paste template library; this is the reason why its member */
230 /* functions are not declared static (in the general case, they should). */
231 /**************************************************************************/
233 NoopProperty *
234 noopprop_new(const PropDescription *pdesc, PropDescToPropPredicate reason)
236 NoopProperty *prop = g_new(NoopProperty,1);
237 initialize_property(&prop->common, pdesc, reason);
238 return prop;
241 void
242 noopprop_free(NoopProperty *prop)
244 g_free(prop);
247 NoopProperty *
248 noopprop_copy(NoopProperty *src)
250 NoopProperty *prop =
251 (NoopProperty *)src->common.ops->new_prop(src->common.descr,
252 src->common.reason);
253 copy_init_property(&prop->common,&src->common);
254 return prop; /* Yes, this one could be just be _new().
255 It's actually a placeholder. */
258 WIDGET *
259 noopprop_get_widget(NoopProperty *prop, PropDialog *dialog)
261 return NULL;
264 void
265 noopprop_reset_widget(NoopProperty *prop, WIDGET *widget)
269 void
270 noopprop_set_from_widget(NoopProperty *prop, WIDGET *widget)
274 void
275 noopprop_load(NoopProperty *prop, AttributeNode attr, DataNode data)
279 void
280 noopprop_save(NoopProperty *prop, AttributeNode attr)
284 gboolean
285 noopprop_can_merge(const PropDescription *pd1, const PropDescription *pd2)
287 return TRUE;
290 gboolean
291 noopprop_cannot_merge(const PropDescription *pd1, const PropDescription *pd2)
293 return TRUE;
296 void
297 noopprop_get_from_offset(const NoopProperty *prop,
298 void *base, guint offset, guint offset2)
302 void
303 noopprop_set_from_offset(NoopProperty *prop,
304 void *base, guint offset, guint offset2)
308 static const PropertyOps noopprop_ops = {
309 (PropertyType_New) noopprop_new,
310 (PropertyType_Free) noopprop_free,
311 (PropertyType_Copy) noopprop_copy,
312 (PropertyType_Load) noopprop_load,
313 (PropertyType_Save) noopprop_save,
314 (PropertyType_GetWidget) noopprop_get_widget,
315 (PropertyType_ResetWidget) noopprop_reset_widget,
316 (PropertyType_SetFromWidget) noopprop_set_from_widget,
318 (PropertyType_CanMerge) noopprop_can_merge, /* but we have noopprop_cannot_merge */
319 (PropertyType_GetFromOffset) noopprop_get_from_offset,
320 (PropertyType_SetFromOffset) noopprop_set_from_offset
323 /***************************************************************************/
324 /* The INVALID property type. It is mostly useful to serve a library. */
325 /* Each time its code is executed, a g_assert_not_reached() will be run... */
326 /***************************************************************************/
328 InvalidProperty *
329 invalidprop_new(const PropDescription *pdesc,
330 PropDescToPropPredicate reason)
332 g_assert_not_reached();
333 return NULL;
336 void
337 invalidprop_free(InvalidProperty *prop)
339 g_assert_not_reached();
342 InvalidProperty *
343 invalidprop_copy(InvalidProperty *src)
345 g_assert_not_reached();
346 return NULL;
349 WIDGET *
350 invalidprop_get_widget(InvalidProperty *prop, PropDialog *dialog)
352 g_assert_not_reached();
353 return NULL;
356 void
357 invalidprop_reset_widget(InvalidProperty *prop, WIDGET *widget)
359 g_assert_not_reached();
362 void
363 invalidprop_set_from_widget(InvalidProperty *prop, WIDGET *widget)
365 g_assert_not_reached();
368 void
369 invalidprop_load(InvalidProperty *prop, AttributeNode attr, DataNode data)
371 g_assert_not_reached();
374 void
375 invalidprop_save(InvalidProperty *prop, AttributeNode attr)
377 g_assert_not_reached();
380 gboolean
381 invalidprop_can_merge(const PropDescription *pd1, const PropDescription *pd2)
383 g_assert_not_reached();
384 return TRUE;
387 void
388 invalidprop_get_from_offset(const InvalidProperty *prop,
389 void *base, guint offset, guint offset2)
391 g_assert_not_reached();
394 void
395 invalidprop_set_from_offset(InvalidProperty *prop,
396 void *base, guint offset, guint offset2)
398 g_assert_not_reached();
401 static const PropertyOps invalidprop_ops = {
402 (PropertyType_New) invalidprop_new,
403 (PropertyType_Free) invalidprop_free,
404 (PropertyType_Copy) invalidprop_copy,
405 (PropertyType_Load) invalidprop_load,
406 (PropertyType_Save) invalidprop_save,
407 (PropertyType_GetWidget) invalidprop_get_widget,
408 (PropertyType_ResetWidget) invalidprop_reset_widget,
409 (PropertyType_SetFromWidget) invalidprop_set_from_widget,
411 (PropertyType_CanMerge) invalidprop_can_merge,
412 (PropertyType_GetFromOffset) invalidprop_get_from_offset,
413 (PropertyType_SetFromOffset) invalidprop_set_from_offset
416 /***************************************************************************/
417 /* The UNIMPLEMENTED property type. It is mostly useful to serve a library */
418 /* for unfinished property types. */
419 /***************************************************************************/
421 UnimplementedProperty *
422 unimplementedprop_new(const PropDescription *pdesc,
423 PropDescToPropPredicate reason)
425 g_warning(G_GNUC_FUNCTION " for property %s",pdesc->name);
426 return NULL;
429 void
430 unimplementedprop_free(UnimplementedProperty *prop)
432 g_warning(G_GNUC_FUNCTION " for property %s",prop->common.descr->name);
435 UnimplementedProperty *
436 unimplementedprop_copy(UnimplementedProperty *src)
438 g_warning(G_GNUC_FUNCTION " for property %s",src->common.descr->name);
439 return NULL;
442 WIDGET *
443 unimplementedprop_get_widget(UnimplementedProperty *prop, PropDialog *dialog)
445 g_warning(G_GNUC_FUNCTION " for property %s",prop->common.descr->name);
446 return NULL;
449 void
450 unimplementedprop_reset_widget(UnimplementedProperty *prop, WIDGET *widget)
452 g_warning(G_GNUC_FUNCTION " for property %s",prop->common.descr->name);
455 void
456 unimplementedprop_set_from_widget(UnimplementedProperty *prop, WIDGET *widget)
458 g_warning(G_GNUC_FUNCTION " for property %s",prop->common.descr->name);
461 void
462 unimplementedprop_load(UnimplementedProperty *prop,
463 AttributeNode attr, DataNode data)
465 g_warning(G_GNUC_FUNCTION " for property %s",prop->common.descr->name);
468 void
469 unimplementedprop_save(UnimplementedProperty *prop, AttributeNode attr)
471 g_warning(G_GNUC_FUNCTION " for property %s",prop->common.descr->name);
474 gboolean
475 unimplementedprop_can_merge(const PropDescription *pd1, const PropDescription *pd2)
477 g_warning(G_GNUC_FUNCTION " for property %s/%s",pd1->name,pd2->name);
478 return FALSE;
481 void
482 unimplementedprop_get_from_offset(const UnimplementedProperty *prop,
483 void *base, guint offset, guint offset2)
485 g_warning(G_GNUC_FUNCTION " for property %s",prop->common.descr->name);
488 void
489 unimplementedprop_set_from_offset(UnimplementedProperty *prop,
490 void *base, guint offset, guint offset2)
492 g_warning(G_GNUC_FUNCTION " for property %s",prop->common.descr->name);
495 static const PropertyOps unimplementedprop_ops = {
496 (PropertyType_New) unimplementedprop_new,
497 (PropertyType_Free) unimplementedprop_free,
498 (PropertyType_Copy) unimplementedprop_copy,
499 (PropertyType_Load) unimplementedprop_load,
500 (PropertyType_Save) unimplementedprop_save,
501 (PropertyType_GetWidget) unimplementedprop_get_widget,
502 (PropertyType_ResetWidget) unimplementedprop_reset_widget,
503 (PropertyType_SetFromWidget) unimplementedprop_set_from_widget,
505 (PropertyType_CanMerge) unimplementedprop_can_merge,
506 (PropertyType_GetFromOffset) unimplementedprop_get_from_offset,
507 (PropertyType_SetFromOffset) unimplementedprop_set_from_offset
510 /* ************************************************************** */
512 void
513 prop_basic_register(void)
515 prop_type_register(PROP_TYPE_NOOP,&noopprop_ops);
516 prop_type_register(PROP_TYPE_INVALID,&invalidprop_ops);
517 prop_type_register(PROP_TYPE_UNIMPLEMENTED,&unimplementedprop_ops);