1 /* Dia -- a diagram creation/manipulation program -*- c -*-
2  * Copyright (C) 1998 Alexander Larsson
3  *
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
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22  */
23 
24 #ifndef LIB_PROPERTIES_H
25 #define LIB_PROPERTIES_H
26 
27 #ifndef WIDGET
28 #ifdef GTK_WIDGET
29 #define WIDGET GtkWidget
30 #else
31 #define WIDGET void
32 #endif
33 #endif
34 
35 
36 #ifdef HAVE_STDDEF_H
37 #include <stddef.h>
38 #endif
39 
40 #include <glib.h>
41 #include "diatypes.h"
42 
43 #include "geometry.h"
44 #include "arrows.h"
45 #include "color.h"
46 #include "font.h"
47 #include "dia_xml.h"
48 #include "intl.h"
49 #include "textattr.h"
50 
51 G_BEGIN_DECLS
52 
53 typedef gboolean (*PropDescToPropPredicate)(const PropDescription *pdesc);
54 
55 struct _PropWidgetAssoc {
56   Property *prop;
57   WIDGET *widget;
58 };
59 
60 struct _PropDialog { /* This is to be treated as opaque ! */
61   WIDGET *widget; /* widget of self */
62 
63   GPtrArray *props; /* of Property * */
64   GArray *prop_widgets; /* of PropWidgetAssoc. This is a "flat" listing of
65                            properties and widgets (no nesting information is
66                            kept here) */
67   GList *objects; /* a copy of the objects, to be used as scratch. */
68   GList *copies;  /* The original objects. */
69 
70   GPtrArray *containers;
71   WIDGET *lastcont;
72   WIDGET *curtable;
73   guint currow;
74 };
75 
76 struct _PropEventData {
77   PropDialog *dialog;
78   guint my_index; /* in dialog->propwidgets */
79   WIDGET *widget;
80   Property *self;
81 };
82 
83 typedef gboolean (*PropEventHandler) (DiaObject *obj, Property *prop);
84 
85 struct _PropEventHandlerChain {
86   PropEventHandler handler;
87   PropEventHandlerChain *chain;
88 };
89 
90 /* PropertyType operations : */
91 
92 /* allocate a new, empty property. */
93 typedef Property * (*PropertyType_New) (const PropDescription *pdesc,
94                                     PropDescToPropPredicate reason);
95 /* free the property -- must skip NULL values. */
96 typedef void (* PropertyType_Free)(Property *prop);
97 /* Copy the data member of the property. -- must skip NULL values. */
98 typedef Property *(* PropertyType_Copy)(Property *src);
99 /* Create a widget capable of editing the property. Add it to the last container (or
100    add/remove container levels). */
101 typedef WIDGET *(* PropertyType_GetWidget)(Property *prop,
102                                        PropDialog *dialog);
103 
104 /* Get the value of the property into the widget */
105 typedef void (* PropertyType_ResetWidget)(const Property *prop, WIDGET *widget);
106 /* Set the value of the property from the current value of the widget */
107 typedef void (* PropertyType_SetFromWidget)(Property *prop, WIDGET *widget);
108 /* load/save a property */
109 typedef void (*PropertyType_Load)(Property *prop, AttributeNode attr, DataNode data);
110 typedef void (*PropertyType_Save)(Property *prop, AttributeNode attr);
111 
112 /* If a property descriptor can be merged with another
113    (DONT_MERGE has already been handled) */
114 typedef gboolean (*PropertyType_CanMerge)(const PropDescription *pd1,const PropDescription *pd2);
115 typedef void (*PropertyType_GetFromOffset)(const Property *prop,
116                                          void *base, guint offset, guint offset2);
117 typedef void (*PropertyType_SetFromOffset)(Property *prop,
118                                          void *base, guint offset, guint offset2);
119 typedef int (*PropertyType_GetDataSize)(Property *prop);
120 
121 
122 struct _PropertyOps {
123   PropertyType_New  new_prop;
124   PropertyType_Free free;
125   PropertyType_Copy copy;
126   PropertyType_Load load;
127   PropertyType_Save save;
128   PropertyType_GetWidget get_widget;
129   PropertyType_ResetWidget reset_widget;
130   PropertyType_SetFromWidget set_from_widget;
131 
132   PropertyType_CanMerge can_merge;
133 
134   PropertyType_GetFromOffset get_from_offset;
135   PropertyType_SetFromOffset set_from_offset;
136   PropertyType_GetDataSize get_data_size;
137 };
138 
139 typedef const gchar *PropertyType;
140 
141 /* Basic types (can be used as building blocks) : */
142 #define PROP_TYPE_INVALID "invalid"   /* InvalidProperty */
143 #define PROP_TYPE_NOOP "noop"         /* NoopProperty */
144 #define PROP_TYPE_UNIMPLEMENTED "unimplemented" /* UnimplementedProperty */
145 
146 /* Integral types : */
147 #define PROP_TYPE_CHAR "char"             /* CharProperty */
148 #define PROP_TYPE_BOOL "bool"             /* BoolProperty */
149 #define PROP_TYPE_INT "int"               /* IntProperty */
150 #define PROP_TYPE_INTARRAY "intarray"     /* IntarrayProperty */
151 #define PROP_TYPE_ENUM "enum"             /* EnumProperty */
152 #define PROP_TYPE_ENUMARRAY "enumarray"   /* EnumarrayProperty */
153 
154 /* Text types : */
155 #define PROP_TYPE_MULTISTRING "multistring"  /* StringProperty */
156 /* (same as STRING but with (gint)extra_data lines) */
157 #define PROP_TYPE_STRING "string"            /* StringProperty */
158 #define PROP_TYPE_FILE "file"                /* StringProperty */
159 #define PROP_TYPE_TEXT "text" /* can't be visible */ /* TextProperty */
160 #define PROP_TYPE_STRINGLIST "stringlist" /* can't be visible */ /* StringListProperty */
161 
162 /* Geometric types : */
163 #define PROP_TYPE_REAL "real"                /* RealProperty */
164 #define PROP_TYPE_LENGTH "length"            /* LengthProperty */
165 #define PROP_TYPE_FONTSIZE "fontsize"        /* FontsizeProperty */
166 #define PROP_TYPE_POINT "point"              /* PointProperty */
167 #define PROP_TYPE_POINTARRAY "pointarray"    /* PointarrayProperty */
168 #define PROP_TYPE_BEZPOINT "bezpoint"        /* BezPointProperty */
169 #define PROP_TYPE_BEZPOINTARRAY "bezpointarray" /* BezPointarrayProperty */
170 #define PROP_TYPE_RECT "rect"                /* RectProperty */
171 #define PROP_TYPE_ENDPOINTS "endpoints"      /* EndpointsProperty */
172 #define PROP_TYPE_CONNPOINT_LINE "connpoint_line"  /* Connpoint_LineProperty */
173 
174 /* Attribute types : */
175 #define PROP_TYPE_LINESTYLE "linestyle"    /* LinestyleProperty */
176 #define PROP_TYPE_ARROW "arrow"            /* ArrowProperty */
177 #define PROP_TYPE_COLOUR "colour"          /* ColorProperty */
178 #define PROP_TYPE_FONT "font"              /* FontProperty */
179 
180 /* Widget types : */
181 #define PROP_TYPE_STATIC "static"          /* StaticProperty */
182 /* (tooltip is used as a (potentially big) static label) */
183 #define PROP_TYPE_BUTTON "button"          /* ButtonProperty */
184 /* (tooltip is the button's label. Put an empty description). */
185 #define PROP_TYPE_NOTEBOOK_BEGIN "nb_begin" /* NotebookProperty */
186 #define PROP_TYPE_NOTEBOOK_END "nb_end"     /* NotebookProperty */
187 #define PROP_TYPE_NOTEBOOK_PAGE "nb_page"   /* NotebookProperty */
188 #define PROP_TYPE_MULTICOL_BEGIN "mc_begin" /* MulticolProperty */
189 #define PROP_TYPE_MULTICOL_END "mc_end"     /* MulticolProperty */
190 #define PROP_TYPE_MULTICOL_COLUMN "mc_col"  /* MulticolProperty */
191 #define PROP_TYPE_FRAME_BEGIN "f_begin" /* FrameProperty */
192 #define PROP_TYPE_FRAME_END "f_end"     /* FrameProperty */
193 #define PROP_TYPE_LIST "list"  /* ListProperty */
194 /* (offset is a GPtrArray of (const gchar *). offset2 is a gint, index of the
195    active item, -1 if none active.) */
196 
197 /* Special types : */
198 #define PROP_TYPE_SARRAY "sarray" /* ArrayProperty */
199 #define PROP_TYPE_DARRAY "darray" /* ArrayProperty */
200 #define PROP_TYPE_DICT "dict" /* DictProperty */
201 
202 /* **************************************************************** */
203 
204 struct _PropDescription {
205   const gchar *name;
206   PropertyType type;
207   guint flags;
208   const gchar *description;
209   const gchar *tooltip;
210 
211   /* Holds some extra data whose meaning is dependent on the property type.
212    * For example, int or float may use bounds for a spin button, and enums
213    * may use a list of string names for enumeration values. */
214   gpointer extra_data;
215 
216   /* if the property widget can send events when it's somehow interacted with,
217      control will be passed to object_type-supplied event_handler, and
218      event->dialog->obj_copy will be current with the dialog's values.
219      When control comes back, event->dialog->obj_copy's properties will be
220      brought back into the dialog. */
221   PropEventHandler event_handler;
222 
223   GQuark quark; /* quark for property name -- helps speed up lookups. */
224   GQuark type_quark;
225 
226   /* only used by dynamically constructed property descriptors (eg. groups) */
227   PropEventHandlerChain chain_handler;
228 
229   const PropertyOps *ops;
230 };
231 
232 #define PROP_FLAG_VISIBLE   0x0001
233 #define PROP_FLAG_DONT_SAVE 0x0002
234 #define PROP_FLAG_DONT_MERGE 0x0004 /* in case group properties are edited */
235 #define PROP_FLAG_NO_DEFAULTS 0x0008 /* don't edit this in defaults dlg. */
236 #define PROP_FLAG_LOAD_ONLY 0x0010 /* for loading old formats */
237 #define PROP_FLAG_STANDARD 0x0020 /* One of the default toolbox props */
238 #define PROP_FLAG_MULTIVALUE 0x0040 /* Multiple values for prop in group */
239 #define PROP_FLAG_WIDGET_ONLY 0x0080 /* only cosmetic property, no data */
240 #define PROP_FLAG_OPTIONAL 0x0100 /* don't complain if it does not exist */
241 
242 typedef enum {PROP_UNION, PROP_INTERSECTION} PropMergeOption;
243 
244 #define PROP_DESC_END { NULL, 0, 0, NULL, NULL, NULL, 0 }
245 
246 /* extra data pointers for various property types */
247 struct _PropNumData {
248   gfloat min, max, step;
249 };
250 struct _PropEnumData {
251   const gchar *name;
252   guint enumv;
253 };
254 
255 typedef gpointer (*NewRecordFunc)(void);
256 typedef void (*FreeRecordFunc)(gpointer rec);
257 
258 struct _PropDescCommonArrayExtra { /* don't use this directly.
259                                       Use one of below */
260   PropDescription *record;
261   PropOffset      *offsets; /* the offsets into the structs in the list/array */
262   const gchar     *composite_type; /* can be NULL. */
263 };
264 
265 struct _PropDescDArrayExtra {
266   PropDescCommonArrayExtra common; /* must be first */
267   NewRecordFunc newrec;
268   FreeRecordFunc freerec;
269 };
270 
271 struct  _PropDescSArrayExtra {
272   PropDescCommonArrayExtra common; /* must be first */
273   guint element_size;  /* sizeof(record) */
274   guint array_len;
275 };
276 
277 
278 /* ******************* */
279 /* The Property itself */
280 /* ******************* */
281 struct _Property {
282   const gchar *name;
283   GQuark name_quark;
284   PropertyType type;
285   GQuark type_quark;
286   const PropDescription *descr;
287   gpointer extra_data;
288   PropEventData self;
289   PropEventHandler event_handler;
290   PropDescToPropPredicate reason; /* why has this property been created from
291                                      the pdesc ? */
292   guint experience;       /* flags PXP_.... */
293 
294   const PropertyOps *ops;       /* points to common_prop_ops */
295   const PropertyOps *real_ops;  /* == descr->ops */
296 };
297 
298 /* prop->experience flags */
299 #define PXP_COPIED           0x00000001  /* has been copied */
300 #define PXP_COPY             0x00000002  /* is a copy */
301 #define PXP_GET_WIDGET       0x00000004
302 #define PXP_RESET_WIDGET     0x00000008
303 #define PXP_SET_FROM_WIDGET  0x00000010
304 #define PXP_LOADED           0x00000020
305 #define PXP_SAVED            0x00000040
306 #define PXP_GFO              0x00000080
307 #define PXP_SFO              0x00000100
308 #define PXP_NOTSET           0x00000200
309 #define PXP_SHAMELESS        0xFFFFFFFF
310 
311 /* ***************************************************************** */
312 /* Operations on property descriptors and property descriptor lists. */
313 
314 void prop_desc_list_calculate_quarks(PropDescription *plist);
315 /* plist must have all quarks calculated in advance */
316 const PropDescription *prop_desc_list_find_prop(const PropDescription *plist,
317                                                 const gchar *name);
318 /* finds the real handler in case there are several levels of indirection */
319 PropEventHandler prop_desc_find_real_handler(const PropDescription *pdesc);
320 /* free a handler indirection list */
321 void prop_desc_free_handler_chain(PropDescription *pdesc);
322 /* free a handler indirection list in a list of descriptors */
323 void prop_desc_list_free_handler_chain(PropDescription *pdesc);
324 /* insert an event handler */
325 void prop_desc_insert_handler(PropDescription *pdesc,
326                               PropEventHandler handler);
327 
328 /* operations on lists of property description lists */
329 PropDescription *prop_desc_lists_union(GList *plists);
330 PropDescription *prop_desc_lists_intersection(GList *plists);
331 
332 
333 /* ********************************************* */
334 /* Functions for dealing with the Type Registry  */
335 void prop_type_register(PropertyType type, const PropertyOps *ops);
336 const PropertyOps *prop_type_get_ops(PropertyType type);
337 
338 /* *********************************************************** */
339 /* functions for manipulating a property array.                */
340 
341 void       prop_list_free(GPtrArray *plist);
342 
343 
344 /* copies the whole property structure, including the data. */
345 GPtrArray *prop_list_copy(GPtrArray *plist);
346 /* copies the whole property structure, excluding the data. */
347 GPtrArray *prop_list_copy_empty(GPtrArray *plist);
348 /* Appends copies of the properties in the second list to the first. */
349 void prop_list_add_list (GPtrArray *props, const GPtrArray *ptoadd);
350 
351 GPtrArray *prop_list_from_descs(const PropDescription *plist,
352                                 PropDescToPropPredicate pred);
353 
354 GPtrArray *prop_list_from_single(Property *prop);
355 
356 /* Some predicates: */
357 gboolean pdtpp_true(const PropDescription *pdesc); /* always true */
358 gboolean pdtpp_is_visible(const PropDescription *pdesc);
359 gboolean pdtpp_is_visible_no_standard(const PropDescription *pdesc);
360 gboolean pdtpp_is_not_visible(const PropDescription *pdesc);
361 gboolean pdtpp_do_save(const PropDescription *pdesc);
362 gboolean pdtpp_do_save_no_standard(const PropDescription *pdesc);
363 gboolean pdtpp_do_load(const PropDescription *pdesc);
364 gboolean pdtpp_do_not_save(const PropDescription *pdesc);
365 /* all but DONT_MERGE and NO_DEFAULTS: */
366 gboolean pdtpp_defaults(const PropDescription *pdesc);
367 /* actually used for the "reason" parameter, not as predicates (synonyms for pdtpp_true) */
368 gboolean pdtpp_synthetic(const PropDescription *pdesc);
369 gboolean pdtpp_from_object(const PropDescription *pdesc);
370 
371 
372 /* Swallows the property into a single property list. Can be given NULL.
373    Don't free yourself the property afterwards; prop_list_free() the list
374    instead.
375    You regain responsibility for the property if you g_ptr_array_destroy() the
376    list. */
377 GPtrArray *prop_list_of_single(Property *prop);
378 
379 /* Create a new property of the required type, with the required name.
380    A PropDescription might be created on the fly. The property's value is not
381    initialised (actually, it's zero). */
382 Property *make_new_prop(const char *name, PropertyType type, guint flags);
383 
384 
385 
386 /* Offset to fields in objects */
387 
388 /* calculates the offset of a structure member within the structure */
389 #ifndef offsetof
390 #define offsetof(type, member) ( (int) & ((type*)0) -> member )
391 #endif
392 struct _PropOffset {
393   const gchar *name;
394   PropertyType type;
395   int offset;
396   int offset2; /* maybe for point lists, etc */
397   GQuark name_quark;
398   GQuark type_quark;
399   const PropertyOps *ops;
400 };
401 
402 /* ************************************************ */
403 /* routines used by Objects or to deal with Objects */
404 
405 /* returns TRUE if this object can be handled (at least in part) through this
406    library. */
407 gboolean object_complies_with_stdprop(const DiaObject *obj);
408 gboolean objects_comply_with_stdprop(GList *objects);
409 
410 void object_list_get_props(GList *objects, GPtrArray *props);
411 
412 /* will do whatever is needed to make the PropDescription * list look good to
413    the rest of the properties code. Can return NULL. */
414 const PropDescription *object_get_prop_descriptions(const DiaObject *obj);
415 const PropDescription *object_list_get_prop_descriptions(GList *objects,
416 							 PropMergeOption option);
417 
418 gboolean object_get_props_from_offsets(DiaObject *obj, PropOffset *offsets,
419 				       GPtrArray *props);
420 gboolean object_set_props_from_offsets(DiaObject *obj, PropOffset *offsets,
421 				       GPtrArray *props);
422 
423 /* apply some properties and return a corresponding object change */
424 ObjectChange *object_apply_props(DiaObject *obj, GPtrArray *props);
425 
426 /* standard properties dialogs that can be used for objects that
427  * implement describe_props, get_props and set_props.
428  * If is_default is set, this is a default dialog, not an object dialog.
429  */
430 WIDGET *object_create_props_dialog     (DiaObject *obj, gboolean is_default);
431 WIDGET *object_list_create_props_dialog(GList *obj, gboolean is_default);
432 ObjectChange *object_apply_props_from_dialog (DiaObject *obj, WIDGET *dialog);
433 
434 /* create a property from the object's property descriptors. To be freed with
435    prop->ops->free(prop); or put it into a single property list. NULL if object
436    has nothing matching. Property's value is initialised by the object.
437    Serve cold. */
438 Property *object_prop_by_name(DiaObject *obj, const char *name);
439 Property *object_prop_by_name_type(DiaObject *obj, const char *name, const char *type);
440 
441 /* standard way to load/save properties of an object */
442 void          object_load_props(DiaObject *obj, ObjectNode obj_node);
443 void          object_save_props(DiaObject *obj, ObjectNode obj_node);
444 
445 /* standard way to copy the properties of an object into another (of the
446    same type) */
447 void          object_copy_props(DiaObject *dest, const DiaObject *src,
448                                 gboolean is_default);
449 
450 /* Return a reference to objects property with 'name' or NULL */
451 Property     *object_get_prop_by_name (DiaObject *obj, const char* name);
452 
453 /* ************************************************************* */
454 
455 void stdprops_init(void);
456 
457 /* ************************************************************* */
458 
459 /* standard properties.  By using these, the intersection of the properties
460  * of a number of objects should be greater, making setting properties on
461  * groups better. */
462 
463 /* HB: exporting the following two vars by GIMPVAR==dllexport/dllimport,
464  * does mean the pointers used below have to be calculated
465  * at run-time by the loader, because they will exist
466  * only once in the process space and dynamic link libraries may be
467  * relocated. As a result their address is no longer constant.
468  * Indeed it causes compile time errors with MSVC (initialzer
469  * not a constant).
470  * To fix it they are moved form properties.c and declared as static
471  * on Win32
472  */
473 #ifdef G_OS_WIN32
474 static PropNumData prop_std_line_width_data = { 0.0f, 10.0f, 0.01f };
475 static PropNumData prop_std_text_height_data = { 0.1f, 10.0f, 0.1f };
476 static PropEnumData prop_std_text_align_data[] = {
477   { N_("Left"), ALIGN_LEFT },
478   { N_("Center"), ALIGN_CENTER },
479   { N_("Right"), ALIGN_RIGHT },
480   { NULL, 0 }
481 };
482 #else
483 extern PropNumData prop_std_line_width_data, prop_std_text_height_data;
484 extern PropEnumData prop_std_text_align_data[];
485 #endif
486 
487 #define PROP_STDNAME_LINE_WIDTH "line_width"
488 #define PROP_STDTYPE_LINE_WIDTH PROP_TYPE_LENGTH
489 #define PROP_STD_LINE_WIDTH \
490   { PROP_STDNAME_LINE_WIDTH, PROP_STDTYPE_LINE_WIDTH, PROP_FLAG_VISIBLE|PROP_FLAG_STANDARD, \
491     N_("Line width"), NULL, &prop_std_line_width_data }
492 #define PROP_STD_LINE_WIDTH_OPTIONAL \
493   { PROP_STDNAME_LINE_WIDTH, PROP_STDTYPE_LINE_WIDTH, PROP_FLAG_VISIBLE|PROP_FLAG_STANDARD|PROP_FLAG_OPTIONAL, \
494     N_("Line width"), NULL, &prop_std_line_width_data }
495 #define PROP_STD_LINE_COLOUR \
496   { "line_colour", PROP_TYPE_COLOUR, PROP_FLAG_VISIBLE|PROP_FLAG_STANDARD, \
497     N_("Line color"), NULL, NULL }
498 #define PROP_STD_LINE_COLOUR_OPTIONAL \
499   { "line_colour", PROP_TYPE_COLOUR, PROP_FLAG_VISIBLE|PROP_FLAG_STANDARD|PROP_FLAG_OPTIONAL, \
500     N_("Line color"), NULL, NULL }
501 #define PROP_STD_LINE_STYLE \
502   { "line_style", PROP_TYPE_LINESTYLE, PROP_FLAG_VISIBLE|PROP_FLAG_STANDARD, \
503     N_("Line style"), NULL, NULL }
504 #define PROP_STD_LINE_STYLE_OPTIONAL \
505   { "line_style", PROP_TYPE_LINESTYLE, PROP_FLAG_VISIBLE|PROP_FLAG_STANDARD|PROP_FLAG_OPTIONAL, \
506     N_("Line style"), NULL, NULL }
507 
508 #define PROP_STD_FILL_COLOUR \
509   { "fill_colour", PROP_TYPE_COLOUR, PROP_FLAG_VISIBLE|PROP_FLAG_STANDARD, \
510     N_("Fill color"), NULL, NULL }
511 #define PROP_STD_FILL_COLOUR_OPTIONAL \
512   { "fill_colour", PROP_TYPE_COLOUR, PROP_FLAG_VISIBLE|PROP_FLAG_STANDARD|PROP_FLAG_OPTIONAL, \
513     N_("Fill color"), NULL, NULL }
514 #define PROP_STD_SHOW_BACKGROUND \
515   { "show_background", PROP_TYPE_BOOL, PROP_FLAG_VISIBLE, \
516     N_("Draw background"), NULL, NULL }
517 #define PROP_STD_SHOW_BACKGROUND_OPTIONAL \
518   { "show_background", PROP_TYPE_BOOL, PROP_FLAG_VISIBLE|PROP_FLAG_OPTIONAL, \
519     N_("Draw background"), NULL, NULL }
520 
521 #define PROP_STD_START_ARROW \
522   { "start_arrow", PROP_TYPE_ARROW, PROP_FLAG_VISIBLE|PROP_FLAG_STANDARD, \
523     N_("Start arrow"), NULL, NULL }
524 #define PROP_STD_END_ARROW \
525   { "end_arrow", PROP_TYPE_ARROW, PROP_FLAG_VISIBLE|PROP_FLAG_STANDARD, \
526     N_("End arrow"), NULL, NULL }
527 
528 #define PROP_STD_TEXT_OPTIONS(options) \
529   { "text", PROP_TYPE_TEXT, (options), \
530     N_("Text"), NULL, NULL }
531 #define PROP_STD_TEXT PROP_STD_TEXT_OPTIONS(PROP_FLAG_DONT_SAVE)
532 #define PROP_STD_SAVED_TEXT PROP_STD_TEXT_OPTIONS(0)
533 
534 #define PROP_STD_TEXT_ALIGNMENT_OPTIONS(options) \
535   { "text_alignment", PROP_TYPE_ENUM, (options), \
536     N_("Text alignment"), NULL, prop_std_text_align_data }
537 #define PROP_STD_TEXT_ALIGNMENT \
538         PROP_STD_TEXT_ALIGNMENT_OPTIONS(PROP_FLAG_VISIBLE|PROP_FLAG_DONT_SAVE)
539 
540 #define PROP_STD_TEXT_FONT_OPTIONS(options) \
541   { "text_font", PROP_TYPE_FONT, (options), N_("Font"), NULL, NULL }
542 #define PROP_STD_TEXT_FONT \
543         PROP_STD_TEXT_FONT_OPTIONS(PROP_FLAG_VISIBLE|PROP_FLAG_DONT_SAVE)
544 
545 #define PROP_STDNAME_TEXT_HEIGHT "text_height"
546 #define PROP_STDTYPE_TEXT_HEIGHT PROP_TYPE_FONTSIZE
547 #define PROP_STD_TEXT_HEIGHT_OPTIONS(options) \
548   { PROP_STDNAME_TEXT_HEIGHT, PROP_STDTYPE_TEXT_HEIGHT, (options), \
549     N_("Font size"), NULL, &prop_std_text_height_data }
550 #define PROP_STD_TEXT_HEIGHT \
551         PROP_STD_TEXT_HEIGHT_OPTIONS(PROP_FLAG_VISIBLE|PROP_FLAG_DONT_SAVE)
552 
553 #define PROP_STD_TEXT_COLOUR_OPTIONS(options) \
554   { "text_colour", PROP_TYPE_COLOUR, (options), \
555     N_("Text color"), NULL, NULL }
556 #define PROP_STD_TEXT_COLOUR \
557         PROP_STD_TEXT_COLOUR_OPTIONS(PROP_FLAG_VISIBLE|PROP_FLAG_DONT_SAVE|PROP_FLAG_STANDARD)
558 #define PROP_STD_TEXT_COLOUR_OPTIONAL \
559         PROP_STD_TEXT_COLOUR_OPTIONS(PROP_FLAG_VISIBLE|PROP_FLAG_DONT_SAVE|PROP_FLAG_STANDARD|PROP_FLAG_OPTIONAL)
560 
561 /* Convenience macros */
562 #define PROP_NOTEBOOK_BEGIN(name) \
563   { "nbook_" name, PROP_TYPE_NOTEBOOK_BEGIN, \
564               PROP_FLAG_VISIBLE|PROP_FLAG_DONT_SAVE|PROP_FLAG_WIDGET_ONLY|PROP_FLAG_DONT_MERGE, NULL, NULL}
565 #define PROP_STD_NOTEBOOK_BEGIN PROP_NOTEBOOK_BEGIN("std")
566 #define PROP_OFFSET_NOTEBOOK_BEGIN(name) \
567   { "nbook_" name, PROP_TYPE_NOTEBOOK_BEGIN, 0}
568 #define PROP_OFFSET_STD_NOTEBOOK_BEGIN PROP_OFFSET_NOTEBOOK_BEGIN("std")
569 
570 #define PROP_NOTEBOOK_END(name) \
571   { "nbook_" name "_end", PROP_TYPE_NOTEBOOK_END, \
572       PROP_FLAG_VISIBLE|PROP_FLAG_DONT_SAVE|PROP_FLAG_WIDGET_ONLY|PROP_FLAG_DONT_MERGE, NULL, NULL}
573 #define PROP_STD_NOTEBOOK_END PROP_NOTEBOOK_END("std")
574 #define PROP_OFFSET_NOTEBOOK_END(name) \
575   { "nbook_" name "_end", PROP_TYPE_NOTEBOOK_END, 0}
576 #define PROP_OFFSET_STD_NOTEBOOK_END PROP_OFFSET_NOTEBOOK_END("std")
577 
578 #define PROP_NOTEBOOK_PAGE(name,flags,descr) \
579   { "nbook_page_" name, PROP_TYPE_NOTEBOOK_PAGE, \
580  PROP_FLAG_VISIBLE|PROP_FLAG_DONT_SAVE|PROP_FLAG_WIDGET_ONLY|PROP_FLAG_DONT_MERGE|flags,descr,NULL}
581 #define PROP_OFFSET_NOTEBOOK_PAGE(name) \
582   { "nbook_page_" name , PROP_TYPE_NOTEBOOK_PAGE, 0}
583 
584 #define PROP_MULTICOL_BEGIN(name) \
585   { "mcol_" name, PROP_TYPE_MULTICOL_BEGIN, \
586               PROP_FLAG_VISIBLE|PROP_FLAG_DONT_SAVE|PROP_FLAG_WIDGET_ONLY, NULL, NULL}
587 #define PROP_OFFSET_MULTICOL_BEGIN(name) \
588   { "mcol_" name, PROP_TYPE_NOTEBOOK_BEGIN, 0}
589 
590 #define PROP_MULTICOL_END(name) \
591   { "mcol_" name "_end", PROP_TYPE_MULTICOL_END, \
592       PROP_FLAG_VISIBLE|PROP_FLAG_DONT_SAVE|PROP_FLAG_WIDGET_ONLY, NULL, NULL}
593 #define PROP_OFFSET_MULTICOL_END(name) \
594   { "mcol_" name "_end", PROP_TYPE_MULTICOL_END, 0}
595 
596 #define PROP_MULTICOL_COLUMN(name) \
597   { "mcol_col_" name, PROP_TYPE_MULTICOL_COLUMN, \
598  PROP_FLAG_VISIBLE|PROP_FLAG_DONT_SAVE|PROP_FLAG_WIDGET_ONLY,NULL,NULL}
599 #define PROP_OFFSET_MULTICOL_COLUMN(name) \
600   { "mcol_col_" name, PROP_TYPE_MULTICOL_COLUMN, 0}
601 
602 #define PROP_FRAME_BEGIN(name,flags,descr) \
603   { "frame_" name, PROP_TYPE_FRAME_BEGIN, \
604               PROP_FLAG_VISIBLE|PROP_FLAG_DONT_SAVE|PROP_FLAG_WIDGET_ONLY|flags, descr, NULL}
605 #define PROP_OFFSET_FRAME_BEGIN(name) \
606   { "frame_" name, PROP_TYPE_FRAME_BEGIN, 0}
607 
608 #define PROP_FRAME_END(name,flags) \
609   { "frame_" name "_end", PROP_TYPE_FRAME_END, \
610       PROP_FLAG_VISIBLE|PROP_FLAG_DONT_SAVE|PROP_FLAG_WIDGET_ONLY|flags, NULL, NULL}
611 #define PROP_OFFSET_FRAME_END(name) \
612   { "frame_" name "_end", PROP_TYPE_FRAME_END, 0}
613 
614 G_END_DECLS
615 
616 #endif
617