don't include dlfcn.h on win32
[dia.git] / lib / prop_inttypes.c
blob0213515f002f494432a5e703bc70f489773a31be
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 * Property types for integral types (and arrays thereof).
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 <stdlib.h> /* strtol */
32 #undef GTK_DISABLE_DEPRECATED /* gtk_signal_connect, gtk_object_set_user_data */
33 #include <gtk/gtk.h>
34 #define WIDGET GtkWidget
35 #include "properties.h"
36 #include "propinternals.h"
38 /***************************/
39 /* The CHAR property type. */
40 /***************************/
42 static CharProperty *
43 charprop_new(const PropDescription *pdesc, PropDescToPropPredicate reason)
45 CharProperty *prop = g_new0(CharProperty,1);
46 initialize_property(&prop->common,pdesc,reason);
47 prop->char_data = 0;
48 return prop;
51 static CharProperty *
52 charprop_copy(CharProperty *src)
54 CharProperty *prop =
55 (CharProperty *)src->common.ops->new_prop(src->common.descr,
56 src->common.reason);
57 copy_init_property(&prop->common,&src->common);
58 prop->char_data = src->char_data;
59 return prop;
62 static WIDGET *
63 charprop_get_widget(CharProperty *prop, PropDialog *dialog)
65 GtkWidget *ret = gtk_entry_new();
66 prophandler_connect(&prop->common,GTK_OBJECT(ret),"changed");
67 return ret;
70 static void
71 charprop_reset_widget(CharProperty *prop, WIDGET *widget)
73 gchar ch[7];
74 int unilen = g_unichar_to_utf8 (prop->char_data, ch);
75 ch[unilen] = 0;
76 gtk_entry_set_text(GTK_ENTRY(widget), ch);
79 static void
80 charprop_set_from_widget(CharProperty *prop, WIDGET *widget)
82 gchar *buf = gtk_editable_get_chars(GTK_EDITABLE(widget), 0, 1);
83 prop->char_data = g_utf8_get_char(buf);
84 g_free(buf);
87 static void
88 charprop_load(CharProperty *prop, AttributeNode attr, DataNode data)
90 gchar *str = data_string(data);
92 if (str && str[0]) {
93 prop->char_data = g_utf8_get_char(str);
94 g_free(str);
95 } else {
96 g_warning("Could not read character data for attribute %s",
97 prop->common.name);
101 static void
102 charprop_save(CharProperty *prop, AttributeNode attr)
104 gchar utf[7];
105 gint n = g_unichar_to_utf8 (prop->char_data, utf);
106 utf[n] = 0;
107 data_add_string (attr, utf);
110 static void
111 charprop_get_from_offset(CharProperty *prop,
112 void *base, guint offset, guint offset2)
114 prop->char_data = struct_member(base,offset,gunichar);
117 static void
118 charprop_set_from_offset(CharProperty *prop,
119 void *base, guint offset, guint offset2)
121 struct_member(base,offset,gunichar) = prop->char_data;
125 static const PropertyOps charprop_ops = {
126 (PropertyType_New) charprop_new,
127 (PropertyType_Free) noopprop_free,
128 (PropertyType_Copy) charprop_copy,
129 (PropertyType_Load) charprop_load,
130 (PropertyType_Save) charprop_save,
131 (PropertyType_GetWidget) charprop_get_widget,
132 (PropertyType_ResetWidget) charprop_reset_widget,
133 (PropertyType_SetFromWidget) charprop_set_from_widget,
135 (PropertyType_CanMerge) noopprop_can_merge,
136 (PropertyType_GetFromOffset) charprop_get_from_offset,
137 (PropertyType_SetFromOffset) charprop_set_from_offset
140 /* ************************************ */
143 /***************************/
144 /* The BOOL property type. */
145 /***************************/
147 static void
148 bool_toggled(GtkWidget *wid)
150 if (GTK_TOGGLE_BUTTON(wid)->active)
151 gtk_label_set_text(GTK_LABEL(GTK_BIN(wid)->child), _("Yes"));
152 else
153 gtk_label_set_text(GTK_LABEL(GTK_BIN(wid)->child), _("No"));
156 static Property *
157 boolprop_new(const PropDescription *pdesc, PropDescToPropPredicate reason)
159 BoolProperty *prop = g_new0(BoolProperty,1);
160 initialize_property(&prop->common, pdesc, reason);
161 prop->bool_data = FALSE;
162 return &prop->common;
165 static BoolProperty *
166 boolprop_copy(BoolProperty *src)
168 BoolProperty *prop =
169 (BoolProperty *)src->common.ops->new_prop(src->common.descr,
170 src->common.reason);
171 copy_init_property(&prop->common,&src->common);
172 prop->bool_data = src->bool_data;
173 return prop;
176 static WIDGET *
177 boolprop_get_widget(BoolProperty *prop, PropDialog *dialog)
179 GtkWidget *ret = gtk_toggle_button_new_with_label(_("No"));
180 gtk_signal_connect(GTK_OBJECT(ret), "toggled",
181 GTK_SIGNAL_FUNC(bool_toggled), NULL);
182 prophandler_connect(&prop->common,GTK_OBJECT(ret),"toggled");
183 return ret;
186 static void
187 boolprop_reset_widget(BoolProperty *prop, WIDGET *widget)
189 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget),prop->bool_data);
192 static void
193 boolprop_set_from_widget(BoolProperty *prop, WIDGET *widget)
195 prop->bool_data = GTK_TOGGLE_BUTTON(widget)->active;
198 static void
199 boolprop_load(BoolProperty *prop, AttributeNode attr, DataNode data)
201 prop->bool_data = data_boolean(data);
204 static void
205 boolprop_save(BoolProperty *prop, AttributeNode attr)
207 data_add_boolean(attr, prop->bool_data);
210 static void
211 boolprop_get_from_offset(BoolProperty *prop,
212 void *base, guint offset, guint offset2)
214 prop->bool_data = struct_member(base,offset,gboolean);
217 static void
218 boolprop_set_from_offset(BoolProperty *prop,
219 void *base, guint offset, guint offset2)
221 struct_member(base,offset,gboolean) = prop->bool_data;
225 static const PropertyOps boolprop_ops = {
226 (PropertyType_New) boolprop_new,
227 (PropertyType_Free) noopprop_free,
228 (PropertyType_Copy) boolprop_copy,
229 (PropertyType_Load) boolprop_load,
230 (PropertyType_Save) boolprop_save,
231 (PropertyType_GetWidget) boolprop_get_widget,
232 (PropertyType_ResetWidget) boolprop_reset_widget,
233 (PropertyType_SetFromWidget) boolprop_set_from_widget,
235 (PropertyType_CanMerge) noopprop_can_merge,
236 (PropertyType_GetFromOffset) boolprop_get_from_offset,
237 (PropertyType_SetFromOffset) boolprop_set_from_offset
240 /***************************/
241 /* The INT property type. */
242 /***************************/
244 static IntProperty *
245 intprop_new(const PropDescription *pdesc, PropDescToPropPredicate reason)
247 IntProperty *prop = g_new0(IntProperty,1);
248 initialize_property(&prop->common, pdesc, reason);
249 prop->int_data = 0;
250 return prop;
253 static IntProperty *
254 intprop_copy(IntProperty *src)
256 IntProperty *prop =
257 (IntProperty *)src->common.ops->new_prop(src->common.descr,
258 src->common.reason);
259 copy_init_property(&prop->common,&src->common);
260 prop->int_data = src->int_data;
261 return prop;
264 static WIDGET *
265 intprop_get_widget(IntProperty *prop, PropDialog *dialog)
267 GtkAdjustment *adj = GTK_ADJUSTMENT(gtk_adjustment_new(prop->int_data,
268 G_MININT, G_MAXINT,
269 1.0, 10.0, 10.0));
270 GtkWidget *ret = gtk_spin_button_new(adj, 1.0, 0);
271 gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(ret),TRUE);
272 prophandler_connect(&prop->common,GTK_OBJECT(adj),"value_changed");
274 return ret;
277 static void
278 intprop_reset_widget(IntProperty *prop, WIDGET *widget)
280 GtkAdjustment *adj;
281 if (prop->common.extra_data) {
282 PropNumData *numdata = prop->common.extra_data;
283 adj = GTK_ADJUSTMENT(gtk_adjustment_new(prop->int_data,
284 numdata->min, numdata->max,
285 numdata->step, 10.0 * numdata->step,
286 10.0 * numdata->step));
287 } else {
288 adj = GTK_ADJUSTMENT(gtk_adjustment_new(prop->int_data,
289 G_MININT, G_MAXINT,
290 1.0, 10.0, 10.0));
292 gtk_spin_button_set_adjustment(GTK_SPIN_BUTTON(widget), adj);
293 gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(widget), TRUE);
296 static void
297 intprop_set_from_widget(IntProperty *prop, WIDGET *widget)
299 prop->int_data = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
302 static void
303 intprop_load(IntProperty *prop, AttributeNode attr, DataNode data)
305 prop->int_data = data_int(data);
308 static void
309 intprop_save(IntProperty *prop, AttributeNode attr)
311 data_add_int(attr, prop->int_data);
314 static void
315 intprop_get_from_offset(IntProperty *prop,
316 void *base, guint offset, guint offset2)
318 prop->int_data = struct_member(base,offset,gint);
321 static void
322 intprop_set_from_offset(IntProperty *prop,
323 void *base, guint offset, guint offset2)
325 struct_member(base,offset,gint) = prop->int_data;
328 static const PropertyOps intprop_ops = {
329 (PropertyType_New) intprop_new,
330 (PropertyType_Free) noopprop_free,
331 (PropertyType_Copy) intprop_copy,
332 (PropertyType_Load) intprop_load,
333 (PropertyType_Save) intprop_save,
334 (PropertyType_GetWidget) intprop_get_widget,
335 (PropertyType_ResetWidget) intprop_reset_widget,
336 (PropertyType_SetFromWidget) intprop_set_from_widget,
338 (PropertyType_CanMerge) noopprop_can_merge,
339 (PropertyType_GetFromOffset) intprop_get_from_offset,
340 (PropertyType_SetFromOffset) intprop_set_from_offset
343 /********************************/
344 /* The INTARRAY property type. */
345 /********************************/
347 static IntarrayProperty *
348 intarrayprop_new(const PropDescription *pdesc,
349 PropDescToPropPredicate reason)
351 IntarrayProperty *prop = g_new0(IntarrayProperty,1);
352 initialize_property(&prop->common, pdesc, reason);
353 prop->intarray_data = g_array_new(FALSE,TRUE,sizeof(gint));
354 return prop;
357 static void
358 intarrayprop_free(IntarrayProperty *prop)
360 g_array_free(prop->intarray_data,TRUE);
361 g_free(prop);
364 static IntarrayProperty *
365 intarrayprop_copy(IntarrayProperty *src)
367 guint i;
368 IntarrayProperty *prop =
369 (IntarrayProperty *)src->common.ops->new_prop(src->common.descr,
370 src->common.reason);
371 copy_init_property(&prop->common,&src->common);
372 g_array_set_size(prop->intarray_data,src->intarray_data->len);
373 for (i = 0 ; i < src->intarray_data->len; i++)
374 g_array_index(prop->intarray_data,gint,i) =
375 g_array_index(src->intarray_data,gint,i);
376 return prop;
379 static void
380 intarrayprop_load(IntarrayProperty *prop, AttributeNode attr, DataNode data)
382 guint nvals = attribute_num_data(attr);
383 guint i;
384 g_array_set_size(prop->intarray_data,nvals);
385 for (i=0; (i < nvals) && data; i++, data = data_next(data))
386 g_array_index(prop->intarray_data,gint,i) = data_int(data);
387 if (i != nvals)
388 g_warning("attribute_num_data() and actual data count mismatch "
389 "(shouldn't happen)");
392 static void
393 intarrayprop_save(IntarrayProperty *prop, AttributeNode attr)
395 guint i;
396 for (i = 0; i < prop->intarray_data->len; i++)
397 data_add_int(attr, g_array_index(prop->intarray_data,gint,i));
400 static void
401 intarrayprop_get_from_offset(IntarrayProperty *prop,
402 void *base, guint offset, guint offset2)
404 guint nvals = struct_member(base,offset2,guint);
405 guint i;
406 void *ofs_val = struct_member(base,offset,void *);
407 g_array_set_size(prop->intarray_data,nvals);
408 for (i = 0; i < nvals; i++)
409 g_array_index(prop->intarray_data,gint,i) =
410 struct_member(ofs_val,i * sizeof(gint),gint);
413 static void
414 intarrayprop_set_from_offset(IntarrayProperty *prop,
415 void *base, guint offset, guint offset2)
417 guint nvals = prop->intarray_data->len;
418 gint *vals = g_memdup(&g_array_index(prop->intarray_data,gint,0),
419 sizeof(gint) * nvals);
420 g_free(struct_member(base,offset,gint *));
421 struct_member(base,offset,gint *) = vals;
422 struct_member(base,offset2,guint) = nvals;
425 static const PropertyOps intarrayprop_ops = {
426 (PropertyType_New) intarrayprop_new,
427 (PropertyType_Free) intarrayprop_free,
428 (PropertyType_Copy) intarrayprop_copy,
429 (PropertyType_Load) intarrayprop_load,
430 (PropertyType_Save) intarrayprop_save,
431 (PropertyType_GetWidget) noopprop_get_widget,
432 (PropertyType_ResetWidget) noopprop_reset_widget,
433 (PropertyType_SetFromWidget) noopprop_set_from_widget,
435 (PropertyType_CanMerge) noopprop_can_merge,
436 (PropertyType_GetFromOffset) intarrayprop_get_from_offset,
437 (PropertyType_SetFromOffset) intarrayprop_set_from_offset
440 /***************************/
441 /* The ENUM property type. */
442 /***************************/
444 static EnumProperty *
445 enumprop_new(const PropDescription *pdesc, PropDescToPropPredicate reason)
447 EnumProperty *prop = g_new0(EnumProperty,1);
448 initialize_property(&prop->common, pdesc, reason);
449 prop->enum_data = 0;
450 return prop;
453 static EnumProperty *
454 enumprop_copy(EnumProperty *src)
456 EnumProperty *prop =
457 (EnumProperty *)src->common.ops->new_prop(src->common.descr,
458 src->common.reason);
459 copy_init_property(&prop->common,&src->common);
460 prop->enum_data = src->enum_data;
461 return prop;
464 static WIDGET *
465 enumprop_get_widget(EnumProperty *prop, PropDialog *dialog)
467 GtkWidget *ret;
469 if (prop->common.extra_data) {
470 PropEnumData *enumdata = prop->common.extra_data;
471 GtkWidget *menu;
472 guint i;
474 ret = gtk_option_menu_new();
475 menu = gtk_menu_new();
476 for (i = 0; enumdata[i].name != NULL; i++) {
477 GtkWidget *item = gtk_menu_item_new_with_label(_(enumdata[i].name));
479 gtk_object_set_user_data(GTK_OBJECT(item),
480 GUINT_TO_POINTER(enumdata[i].enumv));
481 gtk_container_add(GTK_CONTAINER(menu), item);
482 gtk_widget_show(item);
483 prophandler_connect(&prop->common,GTK_OBJECT(item),"activate");
485 gtk_option_menu_set_menu(GTK_OPTION_MENU(ret), menu);
486 } else {
487 ret = gtk_entry_new(); /* should use spin button/option menu */
489 return ret;
492 static void
493 enumprop_reset_widget(EnumProperty *prop, WIDGET *widget)
495 if (prop->common.extra_data) {
496 PropEnumData *enumdata = prop->common.extra_data;
497 guint i, pos = 0;
499 for (i = 0; enumdata[i].name != NULL; i++) {
500 if (enumdata[i].enumv == prop->enum_data) {
501 pos = i;
502 break;
505 gtk_option_menu_set_history(GTK_OPTION_MENU(widget), pos);
506 } else {
507 char buf[16];
508 g_snprintf(buf, sizeof(buf), "%d", prop->enum_data);
509 gtk_entry_set_text(GTK_ENTRY(widget), buf);
513 static void
514 enumprop_set_from_widget(EnumProperty *prop, WIDGET *widget)
516 if (GTK_IS_OPTION_MENU(widget)) {
517 prop->enum_data=
518 GPOINTER_TO_UINT(gtk_object_get_user_data(
519 GTK_OBJECT(GTK_OPTION_MENU(widget)->menu_item)));
520 } else {
521 prop->enum_data = strtol(gtk_entry_get_text(GTK_ENTRY(widget)),
522 NULL, 0);
526 static void
527 enumprop_load(EnumProperty *prop, AttributeNode attr, DataNode data)
529 prop->enum_data = data_enum(data);
532 static void
533 enumprop_save(EnumProperty *prop, AttributeNode attr)
535 data_add_enum(attr, prop->enum_data);
538 static void
539 enumprop_get_from_offset(EnumProperty *prop,
540 void *base, guint offset, guint offset2)
542 prop->enum_data = struct_member(base,offset,gint);
545 static void
546 enumprop_set_from_offset(EnumProperty *prop,
547 void *base, guint offset, guint offset2)
549 struct_member(base,offset,gint) = prop->enum_data;
552 static const PropertyOps enumprop_ops = {
553 (PropertyType_New) enumprop_new,
554 (PropertyType_Free) noopprop_free,
555 (PropertyType_Copy) enumprop_copy,
556 (PropertyType_Load) enumprop_load,
557 (PropertyType_Save) enumprop_save,
558 (PropertyType_GetWidget) enumprop_get_widget,
559 (PropertyType_ResetWidget) enumprop_reset_widget,
560 (PropertyType_SetFromWidget) enumprop_set_from_widget,
562 (PropertyType_CanMerge) noopprop_can_merge,
563 (PropertyType_GetFromOffset) enumprop_get_from_offset,
564 (PropertyType_SetFromOffset) enumprop_set_from_offset
567 /********************************/
568 /* The ENUMARRAY property type. */
569 /********************************/
571 static EnumarrayProperty *
572 enumarrayprop_new(const PropDescription *pdesc,
573 PropDescToPropPredicate reason)
575 EnumarrayProperty *prop = g_new0(EnumarrayProperty,1);
576 initialize_property(&prop->common, pdesc, reason);
577 prop->enumarray_data = g_array_new(FALSE,TRUE,sizeof(gint));
578 return prop;
581 static void
582 enumarrayprop_free(EnumarrayProperty *prop)
584 g_array_free(prop->enumarray_data,TRUE);
585 g_free(prop);
588 static EnumarrayProperty *
589 enumarrayprop_copy(EnumarrayProperty *src)
591 guint i;
592 EnumarrayProperty *prop =
593 (EnumarrayProperty *)src->common.ops->new_prop(src->common.descr,
594 src->common.reason);
595 copy_init_property(&prop->common,&src->common);
596 g_array_set_size(prop->enumarray_data,src->enumarray_data->len);
597 for (i = 0 ; i < src->enumarray_data->len; i++)
598 g_array_index(prop->enumarray_data,gint,i) =
599 g_array_index(src->enumarray_data,gint,i);
600 return prop;
603 static void
604 enumarrayprop_load(EnumarrayProperty *prop, AttributeNode attr, DataNode data)
606 guint nvals = attribute_num_data(attr);
607 guint i;
608 g_array_set_size(prop->enumarray_data,nvals);
610 for (i=0; (i < nvals) && data; i++, data = data_next(data))
611 g_array_index(prop->enumarray_data,gint,i) = data_enum(data);
612 if (i != nvals)
613 g_warning("attribute_num_data() and actual data count mismatch "
614 "(shouldn't happen)");
617 static void
618 enumarrayprop_save(EnumarrayProperty *prop, AttributeNode attr)
620 guint i;
621 for (i = 0; i < prop->enumarray_data->len; i++)
622 data_add_enum(attr, g_array_index(prop->enumarray_data,gint,i));
625 static void
626 enumarrayprop_get_from_offset(EnumarrayProperty *prop,
627 void *base, guint offset, guint offset2)
629 guint nvals = struct_member(base,offset2,guint);
630 guint i;
631 void *ofs_val = struct_member(base,offset,void *);
632 g_array_set_size(prop->enumarray_data,nvals);
633 for (i = 0; i < nvals; i++)
634 g_array_index(prop->enumarray_data,gint,i) =
635 struct_member(ofs_val,i * sizeof(gint),gint);
638 static void
639 enumarrayprop_set_from_offset(EnumarrayProperty *prop,
640 void *base, guint offset, guint offset2)
642 guint nvals = prop->enumarray_data->len;
643 gint *vals = g_memdup(&g_array_index(prop->enumarray_data,gint,0),
644 sizeof(gint) * nvals);
645 g_free(struct_member(base,offset,gint *));
646 struct_member(base,offset,gint *) = vals;
647 struct_member(base,offset2,guint) = nvals;
650 static const PropertyOps enumarrayprop_ops = {
651 (PropertyType_New) enumarrayprop_new,
652 (PropertyType_Free) enumarrayprop_free,
653 (PropertyType_Copy) enumarrayprop_copy,
654 (PropertyType_Load) enumarrayprop_load,
655 (PropertyType_Save) enumarrayprop_save,
656 (PropertyType_GetWidget) noopprop_get_widget,
657 (PropertyType_ResetWidget) noopprop_reset_widget,
658 (PropertyType_SetFromWidget) noopprop_set_from_widget,
660 (PropertyType_CanMerge) noopprop_can_merge,
661 (PropertyType_GetFromOffset) enumarrayprop_get_from_offset,
662 (PropertyType_SetFromOffset) enumarrayprop_set_from_offset
665 /* ************************************************************** */
667 void
668 prop_inttypes_register(void)
670 prop_type_register(PROP_TYPE_CHAR,&charprop_ops);
671 prop_type_register(PROP_TYPE_BOOL,&boolprop_ops);
672 prop_type_register(PROP_TYPE_INT,&intprop_ops);
673 prop_type_register(PROP_TYPE_INTARRAY,&intarrayprop_ops);
674 prop_type_register(PROP_TYPE_ENUM,&enumprop_ops);
675 prop_type_register(PROP_TYPE_ENUMARRAY,&enumarrayprop_ops);