* lib/text.h: Added text_get_line() declaration
[dia.git] / lib / prop_inttypes.c
blob4b47362ee2cd9a742777083f03b4ecdd85cea776
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;
124 static int
125 charprop_get_data_size(CharProperty *prop)
127 return sizeof (prop->char_data);
131 static const PropertyOps charprop_ops = {
132 (PropertyType_New) charprop_new,
133 (PropertyType_Free) noopprop_free,
134 (PropertyType_Copy) charprop_copy,
135 (PropertyType_Load) charprop_load,
136 (PropertyType_Save) charprop_save,
137 (PropertyType_GetWidget) charprop_get_widget,
138 (PropertyType_ResetWidget) charprop_reset_widget,
139 (PropertyType_SetFromWidget) charprop_set_from_widget,
141 (PropertyType_CanMerge) noopprop_can_merge,
142 (PropertyType_GetFromOffset) charprop_get_from_offset,
143 (PropertyType_SetFromOffset) charprop_set_from_offset,
144 (PropertyType_GetDataSize) charprop_get_data_size
147 /* ************************************ */
150 /***************************/
151 /* The BOOL property type. */
152 /***************************/
154 static void
155 bool_toggled(GtkWidget *wid)
157 if (GTK_TOGGLE_BUTTON(wid)->active)
158 gtk_label_set_text(GTK_LABEL(GTK_BIN(wid)->child), _("Yes"));
159 else
160 gtk_label_set_text(GTK_LABEL(GTK_BIN(wid)->child), _("No"));
163 static Property *
164 boolprop_new(const PropDescription *pdesc, PropDescToPropPredicate reason)
166 BoolProperty *prop = g_new0(BoolProperty,1);
167 initialize_property(&prop->common, pdesc, reason);
168 prop->bool_data = FALSE;
169 return &prop->common;
172 static BoolProperty *
173 boolprop_copy(BoolProperty *src)
175 BoolProperty *prop =
176 (BoolProperty *)src->common.ops->new_prop(src->common.descr,
177 src->common.reason);
178 copy_init_property(&prop->common,&src->common);
179 prop->bool_data = src->bool_data;
180 return prop;
183 static WIDGET *
184 boolprop_get_widget(BoolProperty *prop, PropDialog *dialog)
186 GtkWidget *ret = gtk_toggle_button_new_with_label(_("No"));
187 gtk_signal_connect(GTK_OBJECT(ret), "toggled",
188 GTK_SIGNAL_FUNC(bool_toggled), NULL);
189 prophandler_connect(&prop->common,GTK_OBJECT(ret),"toggled");
190 return ret;
193 static void
194 boolprop_reset_widget(BoolProperty *prop, WIDGET *widget)
196 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget),prop->bool_data);
199 static void
200 boolprop_set_from_widget(BoolProperty *prop, WIDGET *widget)
202 prop->bool_data = GTK_TOGGLE_BUTTON(widget)->active;
205 static void
206 boolprop_load(BoolProperty *prop, AttributeNode attr, DataNode data)
208 prop->bool_data = data_boolean(data);
211 static void
212 boolprop_save(BoolProperty *prop, AttributeNode attr)
214 data_add_boolean(attr, prop->bool_data);
217 static void
218 boolprop_get_from_offset(BoolProperty *prop,
219 void *base, guint offset, guint offset2)
221 prop->bool_data = struct_member(base,offset,gboolean);
224 static void
225 boolprop_set_from_offset(BoolProperty *prop,
226 void *base, guint offset, guint offset2)
228 struct_member(base,offset,gboolean) = prop->bool_data;
231 static int
232 boolprop_get_data_size(BoolProperty *prop)
234 return sizeof (prop->bool_data);
238 static const PropertyOps boolprop_ops = {
239 (PropertyType_New) boolprop_new,
240 (PropertyType_Free) noopprop_free,
241 (PropertyType_Copy) boolprop_copy,
242 (PropertyType_Load) boolprop_load,
243 (PropertyType_Save) boolprop_save,
244 (PropertyType_GetWidget) boolprop_get_widget,
245 (PropertyType_ResetWidget) boolprop_reset_widget,
246 (PropertyType_SetFromWidget) boolprop_set_from_widget,
248 (PropertyType_CanMerge) noopprop_can_merge,
249 (PropertyType_GetFromOffset) boolprop_get_from_offset,
250 (PropertyType_SetFromOffset) boolprop_set_from_offset,
251 (PropertyType_GetDataSize) boolprop_get_data_size
254 /***************************/
255 /* The INT property type. */
256 /***************************/
258 static IntProperty *
259 intprop_new(const PropDescription *pdesc, PropDescToPropPredicate reason)
261 IntProperty *prop = g_new0(IntProperty,1);
262 initialize_property(&prop->common, pdesc, reason);
263 prop->int_data = 0;
264 return prop;
267 static IntProperty *
268 intprop_copy(IntProperty *src)
270 IntProperty *prop =
271 (IntProperty *)src->common.ops->new_prop(src->common.descr,
272 src->common.reason);
273 copy_init_property(&prop->common,&src->common);
274 prop->int_data = src->int_data;
275 return prop;
278 static WIDGET *
279 intprop_get_widget(IntProperty *prop, PropDialog *dialog)
281 GtkAdjustment *adj = GTK_ADJUSTMENT(gtk_adjustment_new(prop->int_data,
282 G_MININT, G_MAXINT,
283 1.0, 10.0, 10.0));
284 GtkWidget *ret = gtk_spin_button_new(adj, 1.0, 0);
285 gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(ret),TRUE);
286 prophandler_connect(&prop->common,GTK_OBJECT(adj),"value_changed");
288 return ret;
291 static void
292 intprop_reset_widget(IntProperty *prop, WIDGET *widget)
294 GtkAdjustment *adj;
295 if (prop->common.extra_data) {
296 PropNumData *numdata = prop->common.extra_data;
297 adj = GTK_ADJUSTMENT(gtk_adjustment_new(prop->int_data,
298 numdata->min, numdata->max,
299 numdata->step, 10.0 * numdata->step,
300 10.0 * numdata->step));
301 } else {
302 adj = GTK_ADJUSTMENT(gtk_adjustment_new(prop->int_data,
303 G_MININT, G_MAXINT,
304 1.0, 10.0, 10.0));
306 gtk_spin_button_set_adjustment(GTK_SPIN_BUTTON(widget), adj);
307 gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(widget), TRUE);
310 static void
311 intprop_set_from_widget(IntProperty *prop, WIDGET *widget)
313 prop->int_data = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
316 static void
317 intprop_load(IntProperty *prop, AttributeNode attr, DataNode data)
319 prop->int_data = data_int(data);
322 static void
323 intprop_save(IntProperty *prop, AttributeNode attr)
325 data_add_int(attr, prop->int_data);
328 static void
329 intprop_get_from_offset(IntProperty *prop,
330 void *base, guint offset, guint offset2)
332 prop->int_data = struct_member(base,offset,gint);
335 static void
336 intprop_set_from_offset(IntProperty *prop,
337 void *base, guint offset, guint offset2)
339 struct_member(base,offset,gint) = prop->int_data;
342 static int
343 intprop_get_data_size(IntProperty *prop)
345 return sizeof (prop->int_data);
348 static const PropertyOps intprop_ops = {
349 (PropertyType_New) intprop_new,
350 (PropertyType_Free) noopprop_free,
351 (PropertyType_Copy) intprop_copy,
352 (PropertyType_Load) intprop_load,
353 (PropertyType_Save) intprop_save,
354 (PropertyType_GetWidget) intprop_get_widget,
355 (PropertyType_ResetWidget) intprop_reset_widget,
356 (PropertyType_SetFromWidget) intprop_set_from_widget,
358 (PropertyType_CanMerge) noopprop_can_merge,
359 (PropertyType_GetFromOffset) intprop_get_from_offset,
360 (PropertyType_SetFromOffset) intprop_set_from_offset,
361 (PropertyType_GetDataSize) intprop_get_data_size
364 /********************************/
365 /* The INTARRAY property type. */
366 /********************************/
368 static IntarrayProperty *
369 intarrayprop_new(const PropDescription *pdesc,
370 PropDescToPropPredicate reason)
372 IntarrayProperty *prop = g_new0(IntarrayProperty,1);
373 initialize_property(&prop->common, pdesc, reason);
374 prop->intarray_data = g_array_new(FALSE,TRUE,sizeof(gint));
375 return prop;
378 static void
379 intarrayprop_free(IntarrayProperty *prop)
381 g_array_free(prop->intarray_data,TRUE);
382 g_free(prop);
385 static IntarrayProperty *
386 intarrayprop_copy(IntarrayProperty *src)
388 guint i;
389 IntarrayProperty *prop =
390 (IntarrayProperty *)src->common.ops->new_prop(src->common.descr,
391 src->common.reason);
392 copy_init_property(&prop->common,&src->common);
393 g_array_set_size(prop->intarray_data,src->intarray_data->len);
394 for (i = 0 ; i < src->intarray_data->len; i++)
395 g_array_index(prop->intarray_data,gint,i) =
396 g_array_index(src->intarray_data,gint,i);
397 return prop;
400 static void
401 intarrayprop_load(IntarrayProperty *prop, AttributeNode attr, DataNode data)
403 guint nvals = attribute_num_data(attr);
404 guint i;
405 g_array_set_size(prop->intarray_data,nvals);
406 for (i=0; (i < nvals) && data; i++, data = data_next(data))
407 g_array_index(prop->intarray_data,gint,i) = data_int(data);
408 if (i != nvals)
409 g_warning("attribute_num_data() and actual data count mismatch "
410 "(shouldn't happen)");
413 static void
414 intarrayprop_save(IntarrayProperty *prop, AttributeNode attr)
416 guint i;
417 for (i = 0; i < prop->intarray_data->len; i++)
418 data_add_int(attr, g_array_index(prop->intarray_data,gint,i));
421 static void
422 intarrayprop_get_from_offset(IntarrayProperty *prop,
423 void *base, guint offset, guint offset2)
425 guint nvals = struct_member(base,offset2,guint);
426 guint i;
427 void *ofs_val = struct_member(base,offset,void *);
428 g_array_set_size(prop->intarray_data,nvals);
429 for (i = 0; i < nvals; i++)
430 g_array_index(prop->intarray_data,gint,i) =
431 struct_member(ofs_val,i * sizeof(gint),gint);
434 static void
435 intarrayprop_set_from_offset(IntarrayProperty *prop,
436 void *base, guint offset, guint offset2)
438 guint nvals = prop->intarray_data->len;
439 gint *vals = g_memdup(&g_array_index(prop->intarray_data,gint,0),
440 sizeof(gint) * nvals);
441 g_free(struct_member(base,offset,gint *));
442 struct_member(base,offset,gint *) = vals;
443 struct_member(base,offset2,guint) = nvals;
446 static const PropertyOps intarrayprop_ops = {
447 (PropertyType_New) intarrayprop_new,
448 (PropertyType_Free) intarrayprop_free,
449 (PropertyType_Copy) intarrayprop_copy,
450 (PropertyType_Load) intarrayprop_load,
451 (PropertyType_Save) intarrayprop_save,
452 (PropertyType_GetWidget) noopprop_get_widget,
453 (PropertyType_ResetWidget) noopprop_reset_widget,
454 (PropertyType_SetFromWidget) noopprop_set_from_widget,
456 (PropertyType_CanMerge) noopprop_can_merge,
457 (PropertyType_GetFromOffset) intarrayprop_get_from_offset,
458 (PropertyType_SetFromOffset) intarrayprop_set_from_offset
461 /***************************/
462 /* The ENUM property type. */
463 /***************************/
465 static EnumProperty *
466 enumprop_new(const PropDescription *pdesc, PropDescToPropPredicate reason)
468 EnumProperty *prop = g_new0(EnumProperty,1);
469 initialize_property(&prop->common, pdesc, reason);
470 prop->enum_data = 0;
471 return prop;
474 static EnumProperty *
475 enumprop_copy(EnumProperty *src)
477 EnumProperty *prop =
478 (EnumProperty *)src->common.ops->new_prop(src->common.descr,
479 src->common.reason);
480 copy_init_property(&prop->common,&src->common);
481 prop->enum_data = src->enum_data;
482 return prop;
485 static WIDGET *
486 enumprop_get_widget(EnumProperty *prop, PropDialog *dialog)
488 GtkWidget *ret;
490 if (prop->common.extra_data) {
491 PropEnumData *enumdata = prop->common.extra_data;
492 GtkWidget *menu;
493 guint i;
495 ret = gtk_option_menu_new();
496 menu = gtk_menu_new();
497 for (i = 0; enumdata[i].name != NULL; i++) {
498 GtkWidget *item = gtk_menu_item_new_with_label(_(enumdata[i].name));
500 gtk_object_set_user_data(GTK_OBJECT(item),
501 GUINT_TO_POINTER(enumdata[i].enumv));
502 gtk_container_add(GTK_CONTAINER(menu), item);
503 gtk_widget_show(item);
504 prophandler_connect(&prop->common,GTK_OBJECT(item),"activate");
506 gtk_option_menu_set_menu(GTK_OPTION_MENU(ret), menu);
507 } else {
508 ret = gtk_entry_new(); /* should use spin button/option menu */
510 return ret;
513 static void
514 enumprop_reset_widget(EnumProperty *prop, WIDGET *widget)
516 if (prop->common.extra_data) {
517 PropEnumData *enumdata = prop->common.extra_data;
518 guint i, pos = 0;
520 for (i = 0; enumdata[i].name != NULL; i++) {
521 if (enumdata[i].enumv == prop->enum_data) {
522 pos = i;
523 break;
526 gtk_option_menu_set_history(GTK_OPTION_MENU(widget), pos);
527 } else {
528 char buf[16];
529 g_snprintf(buf, sizeof(buf), "%d", prop->enum_data);
530 gtk_entry_set_text(GTK_ENTRY(widget), buf);
534 static void
535 enumprop_set_from_widget(EnumProperty *prop, WIDGET *widget)
537 if (GTK_IS_OPTION_MENU(widget)) {
538 prop->enum_data=
539 GPOINTER_TO_UINT(gtk_object_get_user_data(
540 GTK_OBJECT(GTK_OPTION_MENU(widget)->menu_item)));
541 } else {
542 prop->enum_data = strtol(gtk_entry_get_text(GTK_ENTRY(widget)),
543 NULL, 0);
547 static void
548 enumprop_load(EnumProperty *prop, AttributeNode attr, DataNode data)
550 prop->enum_data = data_enum(data);
553 static void
554 enumprop_save(EnumProperty *prop, AttributeNode attr)
556 data_add_enum(attr, prop->enum_data);
559 static void
560 enumprop_get_from_offset(EnumProperty *prop,
561 void *base, guint offset, guint offset2)
563 prop->enum_data = struct_member(base,offset,gint);
566 static void
567 enumprop_set_from_offset(EnumProperty *prop,
568 void *base, guint offset, guint offset2)
570 struct_member(base,offset,gint) = prop->enum_data;
573 static const PropertyOps enumprop_ops = {
574 (PropertyType_New) enumprop_new,
575 (PropertyType_Free) noopprop_free,
576 (PropertyType_Copy) enumprop_copy,
577 (PropertyType_Load) enumprop_load,
578 (PropertyType_Save) enumprop_save,
579 (PropertyType_GetWidget) enumprop_get_widget,
580 (PropertyType_ResetWidget) enumprop_reset_widget,
581 (PropertyType_SetFromWidget) enumprop_set_from_widget,
583 (PropertyType_CanMerge) noopprop_can_merge,
584 (PropertyType_GetFromOffset) enumprop_get_from_offset,
585 (PropertyType_SetFromOffset) enumprop_set_from_offset
588 /********************************/
589 /* The ENUMARRAY property type. */
590 /********************************/
592 static EnumarrayProperty *
593 enumarrayprop_new(const PropDescription *pdesc,
594 PropDescToPropPredicate reason)
596 EnumarrayProperty *prop = g_new0(EnumarrayProperty,1);
597 initialize_property(&prop->common, pdesc, reason);
598 prop->enumarray_data = g_array_new(FALSE,TRUE,sizeof(gint));
599 return prop;
602 static void
603 enumarrayprop_free(EnumarrayProperty *prop)
605 g_array_free(prop->enumarray_data,TRUE);
606 g_free(prop);
609 static EnumarrayProperty *
610 enumarrayprop_copy(EnumarrayProperty *src)
612 guint i;
613 EnumarrayProperty *prop =
614 (EnumarrayProperty *)src->common.ops->new_prop(src->common.descr,
615 src->common.reason);
616 copy_init_property(&prop->common,&src->common);
617 g_array_set_size(prop->enumarray_data,src->enumarray_data->len);
618 for (i = 0 ; i < src->enumarray_data->len; i++)
619 g_array_index(prop->enumarray_data,gint,i) =
620 g_array_index(src->enumarray_data,gint,i);
621 return prop;
624 static void
625 enumarrayprop_load(EnumarrayProperty *prop, AttributeNode attr, DataNode data)
627 guint nvals = attribute_num_data(attr);
628 guint i;
629 g_array_set_size(prop->enumarray_data,nvals);
631 for (i=0; (i < nvals) && data; i++, data = data_next(data))
632 g_array_index(prop->enumarray_data,gint,i) = data_enum(data);
633 if (i != nvals)
634 g_warning("attribute_num_data() and actual data count mismatch "
635 "(shouldn't happen)");
638 static void
639 enumarrayprop_save(EnumarrayProperty *prop, AttributeNode attr)
641 guint i;
642 for (i = 0; i < prop->enumarray_data->len; i++)
643 data_add_enum(attr, g_array_index(prop->enumarray_data,gint,i));
646 static void
647 enumarrayprop_get_from_offset(EnumarrayProperty *prop,
648 void *base, guint offset, guint offset2)
650 guint nvals = struct_member(base,offset2,guint);
651 guint i;
652 void *ofs_val = struct_member(base,offset,void *);
653 g_array_set_size(prop->enumarray_data,nvals);
654 for (i = 0; i < nvals; i++)
655 g_array_index(prop->enumarray_data,gint,i) =
656 struct_member(ofs_val,i * sizeof(gint),gint);
659 static void
660 enumarrayprop_set_from_offset(EnumarrayProperty *prop,
661 void *base, guint offset, guint offset2)
663 guint nvals = prop->enumarray_data->len;
664 gint *vals = g_memdup(&g_array_index(prop->enumarray_data,gint,0),
665 sizeof(gint) * nvals);
666 g_free(struct_member(base,offset,gint *));
667 struct_member(base,offset,gint *) = vals;
668 struct_member(base,offset2,guint) = nvals;
671 static const PropertyOps enumarrayprop_ops = {
672 (PropertyType_New) enumarrayprop_new,
673 (PropertyType_Free) enumarrayprop_free,
674 (PropertyType_Copy) enumarrayprop_copy,
675 (PropertyType_Load) enumarrayprop_load,
676 (PropertyType_Save) enumarrayprop_save,
677 (PropertyType_GetWidget) noopprop_get_widget,
678 (PropertyType_ResetWidget) noopprop_reset_widget,
679 (PropertyType_SetFromWidget) noopprop_set_from_widget,
681 (PropertyType_CanMerge) noopprop_can_merge,
682 (PropertyType_GetFromOffset) enumarrayprop_get_from_offset,
683 (PropertyType_SetFromOffset) enumarrayprop_set_from_offset
686 /* ************************************************************** */
688 void
689 prop_inttypes_register(void)
691 prop_type_register(PROP_TYPE_CHAR,&charprop_ops);
692 prop_type_register(PROP_TYPE_BOOL,&boolprop_ops);
693 prop_type_register(PROP_TYPE_INT,&intprop_ops);
694 prop_type_register(PROP_TYPE_INTARRAY,&intarrayprop_ops);
695 prop_type_register(PROP_TYPE_ENUM,&enumprop_ops);
696 prop_type_register(PROP_TYPE_ENUMARRAY,&enumarrayprop_ops);