From "External "so" module." thread

On 09/10/2011 10:45 PM, Hans Breuer wrote:
At 11.09.2011 00:15, Paul Chavent wrote:
So you recommend to concentrate my effort on module integration (i work
on a "sozi editor") instead of trying to do an external module ?

Yes. IIRC the main thing blocking the inclusion with Dia was the overlong 
string for sozi_script. I could do that split for you, but I only want to do it 
once. So further updates from you should include the fixed approach.

Looking once more at your patch: there also needs to be some adjustment from 
g_snprintf(..., "... %g ...", ... to g_ascii_formatd(). Otherwise the resulting 
SVG would be broken on system defining a decimal separator other than '.'.

Thanks,
Hans

-------- Hans "at" Breuer "dot" Org -----------
Tell me what you need, and I'll tell you how to
get along without it. -- Dilbert
_______________________________________________
dia-list mailing list
[email protected]
http://mail.gnome.org/mailman/listinfo/dia-list
FAQ at http://live.gnome.org/Dia/Faq
Main page at http://live.gnome.org/Dia




Hello mailing list.

I give you a new version of the sozi patch.

I fixed the long lines issue.
I replaced gsnprintf by gstrdup and g_ascii_formatd().

I hope new feedbacks.

Regards.

Paul.
>From b1084baa5fb068339278875ee3516aa23f1bd972 Mon Sep 17 00:00:00 2001
From: Paul Chavent <[email protected]>
Date: Mon, 12 Sep 2011 23:46:17 +0200
Subject: [PATCH 1/2] Add text properties widget.

---
 lib/prop_text.c |   30 +++++++++++++++++++++++++++---
 1 files changed, 27 insertions(+), 3 deletions(-)

diff --git a/lib/prop_text.c b/lib/prop_text.c
index 6c3c596..277072c 100644
--- a/lib/prop_text.c
+++ b/lib/prop_text.c
@@ -411,6 +411,30 @@ textprop_save(TextProperty *prop, AttributeNode attr)
   text_destroy(text);
 }
 
+static GtkWidget *
+textprop_get_widget(TextProperty *prop, PropDialog *dialog) 
+{ 
+  GtkWidget *ret = gtk_entry_new();
+  gtk_entry_set_activates_default(GTK_ENTRY(ret), TRUE);
+  prophandler_connect(&prop->common, G_OBJECT(ret), "changed");
+  return ret;
+}
+
+static void 
+textprop_reset_widget(TextProperty *prop, GtkWidget *widget)
+{
+  gtk_entry_set_text(GTK_ENTRY(widget),
+                     prop->text_data ? prop->text_data : "");
+}
+
+static void 
+textprop_set_from_widget(TextProperty *prop, GtkWidget *widget) 
+{
+  g_free(prop->text_data);
+  prop->text_data =
+    g_strdup (gtk_entry_get_text (GTK_ENTRY(widget)));
+}
+
 static void 
 textprop_get_from_offset(TextProperty *prop,
                          void *base, guint offset, guint offset2) 
@@ -436,9 +460,9 @@ static const PropertyOps textprop_ops = {
   (PropertyType_Copy) textprop_copy,
   (PropertyType_Load) textprop_load,
   (PropertyType_Save) textprop_save,
-  (PropertyType_GetWidget) noopprop_get_widget,
-  (PropertyType_ResetWidget) noopprop_reset_widget,
-  (PropertyType_SetFromWidget) noopprop_set_from_widget,
+  (PropertyType_GetWidget) textprop_get_widget,
+  (PropertyType_ResetWidget) textprop_reset_widget,
+  (PropertyType_SetFromWidget) textprop_set_from_widget,
 
   (PropertyType_CanMerge) noopprop_can_merge,
   (PropertyType_GetFromOffset) textprop_get_from_offset,
-- 
1.7.4.4

>From e6c08bd627006dfb3c505e7f5bd582b18af7ef56 Mon Sep 17 00:00:00 2001
From: Paul Chavent <[email protected]>
Date: Mon, 12 Sep 2011 23:47:06 +0200
Subject: [PATCH 2/2] Add sozi front end.

---
 objects/Misc/Makefile.am            |    7 +-
 objects/Misc/libmisc.c              |    2 +
 objects/Misc/pixmaps/sozi-frame.xpm |  196 +++++++++
 objects/Misc/sozi-frame.c           |  792 +++++++++++++++++++++++++++++++++++
 objects/Misc/sozi.h                 |  222 ++++++++++
 sheets/Misc.sheet.in                |    3 +
 6 files changed, 1219 insertions(+), 3 deletions(-)
 create mode 100644 objects/Misc/pixmaps/sozi-frame.xpm
 create mode 100644 objects/Misc/sozi-frame.c
 create mode 100644 objects/Misc/sozi.h

diff --git a/objects/Misc/Makefile.am b/objects/Misc/Makefile.am
index 306fae4..64e01ad 100644
--- a/objects/Misc/Makefile.am
+++ b/objects/Misc/Makefile.am
@@ -7,8 +7,8 @@ libmisc_objects_la_SOURCES = \
                        diagram_as_object.c \
                        grid_object.c \
                        measure.c \
-                       tree.c
-
+                       tree.c \
+                        sozi-frame.c
 
 libmisc_objects_la_LDFLAGS = -export-dynamic -module -avoid-version 
$(NO_UNDEFINED)
 
@@ -23,7 +23,8 @@ EXTRA_DIST = \
        pixmaps/grid_object.xpm \
        pixmaps/measure.xpm \
        pixmaps/newgroup.xpm \
-       pixmaps/tree.xpm
+       pixmaps/tree.xpm \
+       pixmaps/sozi-frame.xpm
 
 
 
diff --git a/objects/Misc/libmisc.c b/objects/Misc/libmisc.c
index e72ea9a..65b75a9 100644
--- a/objects/Misc/libmisc.c
+++ b/objects/Misc/libmisc.c
@@ -33,6 +33,7 @@ extern DiaObjectType grid_object_type;
 extern DiaObjectType tree_type;
 extern DiaObjectType measure_type;
 extern DiaObjectType diagram_as_element_type;
+extern DiaObjectType sozi_frame_type;
 
 DIA_PLUGIN_CHECK_INIT
 
@@ -48,6 +49,7 @@ dia_plugin_init(PluginInfo *info)
   object_register_type(&tree_type);
   object_register_type(&measure_type);
   object_register_type(&diagram_as_element_type);
+  object_register_type(&sozi_frame_type);
 
   return DIA_PLUGIN_INIT_OK;
 }
diff --git a/objects/Misc/pixmaps/sozi-frame.xpm 
b/objects/Misc/pixmaps/sozi-frame.xpm
new file mode 100644
index 0000000..e5f3ed3
--- /dev/null
+++ b/objects/Misc/pixmaps/sozi-frame.xpm
@@ -0,0 +1,196 @@
+/* XPM */
+static char * sozi_frame_xpm[] = {
+"22 22 171 2",
+"      c #FFFFFF",
+".     c #FEFEFE",
+"+     c #FDFDFD",
+"@     c #F7F7F8",
+"#     c #D2D2D2",
+"$     c #939393",
+"%     c #8A8A8A",
+"&     c #BEBEBE",
+"*     c #F2F2F2",
+"=     c #FCFCFC",
+"-     c #F3F3F3",
+";     c #FBFBFB",
+">     c #FEFEFF",
+",     c #FCFCFB",
+"'     c #FAF4F1",
+")     c #FAF1EB",
+"!     c #F8F5F2",
+"~     c #BFBFBF",
+"{     c #E4E4E4",
+"]     c #F1F1F1",
+"^     c #ADADAD",
+"/     c #F5F5F5",
+"(     c #BEBABE",
+"_     c #99909A",
+":     c #EDEAED",
+"<     c #ECDCD2",
+"[     c #C3682D",
+"}     c #C64500",
+"|     c #98562A",
+"1     c #BBB6B2",
+"2     c #F8F8F9",
+"3     c #FBFCFB",
+"4     c #FBFCFC",
+"5     c #E8BC9E",
+"6     c #F55A00",
+"7     c #F05F00",
+"8     c #E4BCA1",
+"9     c #F3F8FC",
+"0     c #F6F6F6",
+"a     c #DCDCDC",
+"b     c #CACACA",
+"c     c #CDCDCD",
+"d     c #CBCBC9",
+"e     c #D8D8D7",
+"f     c #FBFBFC",
+"g     c #E7B99A",
+"h     c #F25600",
+"i     c #DD7A39",
+"j     c #E7DDD6",
+"k     c #D0D0D0",
+"l     c #C8C8C8",
+"m     c #989898",
+"n     c #CACBCC",
+"o     c #A3A298",
+"p     c #BFB483",
+"q     c #EEE8D1",
+"r     c #FBFBFA",
+"s     c #FAFBFC",
+"t     c #E6BA9E",
+"u     c #EB5400",
+"v     c #ECA372",
+"w     c #F8FBFD",
+"x     c #ECECEC",
+"y     c #FBFCFE",
+"z     c #D3D1C7",
+"A     c #DDB617",
+"B     c #C4A423",
+"C     c #EFECE1",
+"D     c #FBFDFF",
+"E     c #E5C3AD",
+"F     c #DD5A03",
+"G     c #E8AD85",
+"H     c #F9FFFF",
+"I     c #E6E6E6",
+"J     c #E9E9EA",
+"K     c #CFCECD",
+"L     c #DEBF2D",
+"M     c #C99E00",
+"N     c #EDE9D1",
+"O     c #E4D5CC",
+"P     c #AE6636",
+"Q     c #E2BCA3",
+"R     c #FFFFFE",
+"S     c #E5E5E5",
+"T     c #C8C8C9",
+"U     c #D9DBE5",
+"V     c #DBBD39",
+"W     c #B79A21",
+"X     c #EDEADF",
+"Y     c #ECEAE9",
+"Z     c #A98C7A",
+"`     c #D3B8A6",
+" .    c #E3E3E3",
+"..    c #C7C7C7",
+"+.    c #F1F3FC",
+"@.    c #A5965C",
+"#.    c #BDB496",
+"$.    c #BEBBB8",
+"%.    c #B3ACA7",
+"&.    c #E9E7E7",
+"*.    c #B6B4B4",
+"=.    c #92939A",
+"-.    c #DFDFE3",
+";.    c #ADAEAF",
+">.    c #CCCDCE",
+",.    c #7D898D",
+"'.    c #DCDBDA",
+").    c #EDEDED",
+"!.    c #DADADA",
+"~.    c #9B9B9B",
+"{.    c #DEDEDE",
+"].    c #FFFEFE",
+"^.    c #B4CBD2",
+"/.    c #389CB5",
+"(.    c #6E9CA8",
+"_.    c #DDDDDD",
+":.    c #EAEAEA",
+"<.    c #CECECE",
+"[.    c #B6B6B6",
+"}.    c #E7E7E7",
+"|.    c #B2D0D8",
+"1.    c #1BB6DE",
+"2.    c #00A7D3",
+"3.    c #82AFBB",
+"4.    c #EEEEEE",
+"5.    c #999999",
+"6.    c #F0F0F0",
+"7.    c #E0E0E0",
+"8.    c #F9FCFC",
+"9.    c #1194B5",
+"0.    c #00CEFF",
+"a.    c #23BAE1",
+"b.    c #C3D0D4",
+"c.    c #D4D4D4",
+"d.    c #FAFCFC",
+"e.    c #2E8FA8",
+"f.    c #00BDEF",
+"g.    c #3AB4D3",
+"h.    c #F8F2F1",
+"i.    c #EBEBEB",
+"j.    c #C6C6C6",
+"k.    c #A8A8A8",
+"l.    c #F4F4F4",
+"m.    c #DBE7EB",
+"n.    c #6894A0",
+"o.    c #6C8288",
+"p.    c #A3A1A0",
+"q.    c #949494",
+"r.    c #8F8F8F",
+"s.    c #E2E2E2",
+"t.    c #BABABA",
+"u.    c #CBCACA",
+"v.    c #9A9898",
+"w.    c #F3F2F1",
+"x.    c #E9E9E9",
+"y.    c #E8E8E8",
+"z.    c #F9F9F9",
+"A.    c #F7F7F7",
+"B.    c #A9A9A9",
+"C.    c #C1C1C1",
+"D.    c #D7D7D7",
+"E.    c #F7F6F6",
+"F.    c #FAFAFA",
+"G.    c #5F5F5F",
+"H.    c #B2B2B2",
+"I.    c #F8F8F8",
+"J.    c #D8D8D8",
+"K.    c #909090",
+"L.    c #7D7D7D",
+"M.    c #858585",
+"N.    c #B4B4B4",
+"  .     . .   . . + + . .     .   . .       ",
+"    .         @ # $ % & *     . = - ;   .   ",
+"    > , ' ) ! ~ {     ] ^ /     ( _ :       ",
+"      < [ } | 1 2   . . * ~     3     .   . ",
+"    4 5 6 7 8 9 = .   0 a b c ; d e   > .   ",
+"    f g h i j       . 0 k l m n o p q r . . ",
+"    s t u v w       .       x y z A B C > . ",
+"    D E F G H     .   .   = I J K L M N     ",
+"      O P Q   R         .   S T U V W X   > ",
+"  .   Y Z `   > .       .    ...+.@.#.2     ",
+"    R   $.%.  .   .   . .   &.*.c =.-.      ",
+"    .   n ;.=   .   .       >.,.'.a ).  . . ",
+"  .     !.~.{.  .     . ].^./.(.  . # _.    ",
+"    .   :.<.[.}.  .   + |.1.2.3.    4...5.= ",
+"        * 6.c 7.+     8.9.0.a.b.  .   6.<.+ ",
+"        . c.7.# - . . d.e.f.g.h.            ",
+"    .     i.j.k.l.    > m.n.o.p.$ q.r.s..   ",
+"  .     .   I & t.0 ; ] u.v.w.).x.x.y.z.. . ",
+"          . + A.B.c C.<.D.E.            . . ",
+"F.G.H.i.I.    4.C./ z.; ;   .         .     ",
+". / J.~ K.L.M.N.l..       .   .             ",
+"    . . + + + . . . .     .                 "};
diff --git a/objects/Misc/sozi-frame.c b/objects/Misc/sozi-frame.c
new file mode 100644
index 0000000..1e340a4
--- /dev/null
+++ b/objects/Misc/sozi-frame.c
@@ -0,0 +1,792 @@
+/* Dia -- an diagram creation/manipulation program
+ * Copyright (C) 1999 Alexander Larsson
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+/* standard libs*/
+#include <assert.h>
+#include <math.h>
+
+/* xpath for searching in the svg doc */
+#include <libxml/xpath.h>
+
+/* dia stuff */
+#include "object.h"
+#include "diarenderer.h"
+#include "diasvgrenderer.h"
+#include "properties.h"
+#include "text.h"
+
+/* sozi stuff */
+#include "pixmaps/sozi-frame.xpm"
+#include "sozi.h"
+
+# define M_2_PI 6.28318530718
+
+/******************************************************************************
+ * TODO:
+ * - make a static variable that hold the sequence of the frame (local to a 
+ *   file ?)
+ * - implement transition options
+ * - render sequence number and frame timeout for example
+ * - 
+ *****************************************************************************/
+
+typedef struct _SoziFrame 
+{
+    /* dia object inheritance */
+
+    DiaObject object;
+  
+    /* geometry of the object */
+
+    Point    center;
+    real     width;
+    real     height;
+    real     angle;
+
+    real     cos_angle;
+    real     sin_angle;
+
+    real     m[6]; /** transformation matrix of the unit square */
+
+    /* corners of the object */
+
+    Point    corners[4];
+
+    /* sozi specific stuff */
+
+    int      sequence;
+
+    Text   * title;
+    gboolean hide;
+    gboolean clip;
+    int      timeout;
+ 
+} SoziFrame;
+
+/******************************************************************************
+ * 
+ *****************************************************************************/
+
+static DiaObject * sozi_frame_create(Point *startpoint,
+                                    void *user_data,
+                                    Handle **handle1,
+                                    Handle **handle2);
+static DiaObject * sozi_frame_load(ObjectNode obj_node, int version, const 
char *filename);
+static void        sozi_frame_save(SoziFrame *sozi_frame, ObjectNode obj_node, 
const char *filename);
+
+static ObjectTypeOps sozi_frame_type_ops =
+{
+    (CreateFunc)        sozi_frame_create, /* create */
+    (LoadFunc)          sozi_frame_load,   /* load (== 
object_load_using_properties ?) */
+    (SaveFunc)          sozi_frame_save,   /* save (== 
object_save_using_properties ?) */
+    (GetDefaultsFunc)   NULL,
+    (ApplyDefaultsFunc) NULL,
+};
+
+DiaObjectType sozi_frame_type =
+{
+    "Misc - Sozi Frame",      /* name */
+    0,                        /* version */
+    (char **) sozi_frame_xpm, /* pixmap */
+    &sozi_frame_type_ops,     /* ops */
+    NULL,                     /* pixmap_file */
+    0                         /* default_user_data */
+};
+
+/******************************************************************************
+ * 
+ *****************************************************************************/
+
+static void              sozi_frame_destroy(SoziFrame *sozi_frame);
+
+static void              sozi_frame_draw(SoziFrame *sozi_frame, DiaRenderer 
*renderer);
+
+static real              sozi_frame_distance_from(SoziFrame *sozi_frame, Point 
*point);
+
+static void              sozi_frame_select(SoziFrame *sozi_frame, Point 
*clicked_point,
+                                          DiaRenderer *interactive_renderer);
+
+static DiaObject *       sozi_frame_copy(SoziFrame *sozi_frame);
+
+static ObjectChange*     sozi_frame_move(SoziFrame *sozi_frame, Point *to);
+
+static ObjectChange*     sozi_frame_move_handle(SoziFrame *sozi_frame, Handle 
*handle,
+                                               Point *to, ConnectionPoint *cp,
+                                               HandleMoveReason reason, 
ModifierKeys modifiers);
+
+static PropDescription * sozi_frame_describe_props(SoziFrame *sozi_frame);
+
+static void              sozi_frame_get_props(SoziFrame *sozi_frame, GPtrArray 
*props);
+
+static void              sozi_frame_set_props(SoziFrame *sozi_frame, GPtrArray 
*props);
+
+
+static ObjectOps sozi_frame_ops = 
+{
+  (DestroyFunc)               sozi_frame_destroy,
+  (DrawFunc)                  sozi_frame_draw,
+  (DistanceFunc)              sozi_frame_distance_from,
+  (SelectFunc)                sozi_frame_select,
+  (CopyFunc)                  sozi_frame_copy,
+  (MoveFunc)                  sozi_frame_move,
+  (MoveHandleFunc)            sozi_frame_move_handle,
+  (GetPropertiesFunc)         object_create_props_dialog,
+  (ApplyPropertiesDialogFunc) object_apply_props_from_dialog,
+  (ObjectMenuFunc)            0,
+  (DescribePropsFunc)         sozi_frame_describe_props,
+  (GetPropsFunc)              sozi_frame_get_props,
+  (SetPropsFunc)              sozi_frame_set_props,
+  (TextEditFunc)              0,
+  (ApplyPropertiesListFunc)   object_apply_props,
+};
+
+/******************************************************************************
+ * unit square 
+ *****************************************************************************/
+static const Handle default_handles[4] =
+{
+    {HANDLE_RESIZE_NW, HANDLE_MAJOR_CONTROL, { 0, 0}, HANDLE_NONCONNECTABLE, 
NULL},
+    {HANDLE_RESIZE_SW, HANDLE_MAJOR_CONTROL, { 0, 1}, HANDLE_NONCONNECTABLE, 
NULL},
+    {HANDLE_RESIZE_SE, HANDLE_MAJOR_CONTROL, { 1, 1}, HANDLE_NONCONNECTABLE, 
NULL},
+    {HANDLE_RESIZE_NE, HANDLE_MAJOR_CONTROL, { 1, 0}, HANDLE_NONCONNECTABLE, 
NULL},
+};
+
+static const real sozi_frame_line_width = 0.01;
+
+/******************************************************************************
+ * 
+ *****************************************************************************/
+static void 
+sozi_frame_init(SoziFrame *sozi_frame, Point *center)
+{
+    DiaObject *dia_object;
+    int i;
+    static int sequence = 0;
+    char sequence_str[8];
+
+    dia_object = &sozi_frame->object;
+
+    dia_object->type = &sozi_frame_type;
+    dia_object->ops = &sozi_frame_ops;
+    dia_object->position = *center;
+
+    /* dia_object->bounding_box is set in sozi_frame_update_data */
+
+    dia_object->num_handles = 4;
+    if(dia_object->handles == NULL) {
+       dia_object->handles = g_new0(Handle *, 4);
+    }
+
+    for (i = 0; i < 4; i++) {
+        if(dia_object->handles[i] == NULL) {
+           dia_object->handles[i] = g_new0(Handle, 1);
+        }
+        *dia_object->handles[i] = default_handles[i];
+    }
+
+    dia_object->num_connections = 1;
+    if(dia_object->connections == NULL) {
+        dia_object->connections = g_new0(ConnectionPoint *, 1);
+    }
+
+    for (i = 0; i < 1; i++) {
+        if(dia_object->connections[i] == NULL) {
+            dia_object->connections[i] = g_new0(ConnectionPoint, 1);
+        }
+        dia_object->connections[0]->object = dia_object;
+        dia_object->connections[0]->directions = DIR_ALL;
+    }
+
+    /* dia_object->enclosing_box is set in sozi_frame_update_data */
+
+    sozi_frame->center = *center;
+    sozi_frame->width = 1;
+    sozi_frame->height = 1;
+    sozi_frame->angle = 0;
+
+    /* sozi_frame->cos_angle is set in sozi_frame_update_data */
+    /* sozi_frame->sin_angle is set in sozi_frame_update_data */
+    /* sozi_frame->m is set in sozi_frame_update_data */
+
+    /* sozi_frame->corners are set in sozi_frame_update_data */
+
+    sozi_frame->sequence = sequence++; /* FIXME : it is broken */
+    g_snprintf(sequence_str, sizeof(sequence_str), "%d", sozi_frame->sequence);
+
+    if(sozi_frame->title == NULL) {
+        sozi_frame->title = new_text_default(&sozi_frame->center, 
&color_black, ALIGN_LEFT);
+    }
+    text_set_string(sozi_frame->title, sequence_str);
+
+    sozi_frame->hide = TRUE;
+    sozi_frame->clip = TRUE;
+    sozi_frame->timeout = 0;
+
+}
+
+/******************************************************************************
+ * 
+ *****************************************************************************/
+static void 
+sozi_frame_update_data(SoziFrame *sozi_frame)
+{
+    DiaObject *dia_object;
+    Point title_pos;
+    Rectangle title_bb;
+    int i;
+
+    dia_object = &sozi_frame->object;
+
+    dia_object->position = sozi_frame->center;
+
+    dia_object->bounding_box.left   =  G_MAXFLOAT;
+    dia_object->bounding_box.top    =  G_MAXFLOAT;
+    dia_object->bounding_box.right  = -G_MAXFLOAT;
+    dia_object->bounding_box.bottom = -G_MAXFLOAT;
+
+    if(sozi_frame->angle < 0) {
+       sozi_frame->angle += M_2_PI;
+    }
+    if(M_2_PI < sozi_frame->angle) {
+       sozi_frame->angle -= M_2_PI;
+    }
+    sozi_frame->cos_angle = cos(sozi_frame->angle);
+    sozi_frame->sin_angle = sin(sozi_frame->angle);
+
+    /*
+     *
+     * translate(center.x,center.y) . rotate(angle) . scale(width,height) . 
translate(-0.5,-0.5)
+     *
+     * m
+     * =
+     * | 1 0 x | . | cos(a)  sin(a) 0 | . | w 0 0 | . | 1 0 -0.5 |
+     * | 0 1 y |   | -sin(a) cos(a) 0 |   | 0 h 0 |   | 0 1 -0.5 |
+     * | 0 0 1 |   | 0       0      1 |   | 0 0 1 |   | 0 0 1    |
+     * =
+     * | w*cos(a)  h*sin(a) x-0.5*w*cos(a)-0.5*h*sin(a) |
+     * | -w*sin(a) h*cos(a) y+0.5*w*sin(a)-0.5*h*cos(a) |
+     * | 0         0        1                           |
+     */
+    sozi_frame->m[0] =  sozi_frame->width  * sozi_frame->cos_angle ;
+    sozi_frame->m[1] =  sozi_frame->height * sozi_frame->sin_angle ;
+    sozi_frame->m[2] =  sozi_frame->center.x - 0.5 * sozi_frame->width * 
sozi_frame->cos_angle - 0.5 * sozi_frame->height * sozi_frame->sin_angle;
+    sozi_frame->m[3] = -sozi_frame->width  * sozi_frame->sin_angle ;
+    sozi_frame->m[4] =  sozi_frame->height * sozi_frame->cos_angle ;
+    sozi_frame->m[5] =  sozi_frame->center.y + 0.5 * sozi_frame->width * 
sozi_frame->sin_angle - 0.5 * sozi_frame->height * sozi_frame->cos_angle;
+
+    for (i = 0; i < 4; i++) {
+
+       sozi_frame->corners[i].x = sozi_frame->m[0] * default_handles[i].pos.x 
+ sozi_frame->m[1] * default_handles[i].pos.y + sozi_frame->m[2];
+       sozi_frame->corners[i].y = sozi_frame->m[3] * default_handles[i].pos.x 
+ sozi_frame->m[4] * default_handles[i].pos.y + sozi_frame->m[5];
+
+       dia_object->handles[i]->pos = sozi_frame->corners[i];
+
+        if(i == 0) {
+            dia_object->connections[0]->last_pos = 
dia_object->connections[0]->pos;
+            dia_object->connections[0]->pos = sozi_frame->corners[i];
+        }
+
+       if(sozi_frame->corners[i].x < dia_object->bounding_box.left) {
+           dia_object->bounding_box.left = sozi_frame->corners[i].x - 
sozi_frame_line_width;
+       }
+       if(dia_object->bounding_box.right < sozi_frame->corners[i].x) {
+           dia_object->bounding_box.right = sozi_frame->corners[i].x + 
sozi_frame_line_width;
+       }
+       if(sozi_frame->corners[i].y < dia_object->bounding_box.top) {
+           dia_object->bounding_box.top = sozi_frame->corners[i].y - 
sozi_frame_line_width;
+       }
+       if(dia_object->bounding_box.bottom < sozi_frame->corners[i].y) {
+           dia_object->bounding_box.bottom = sozi_frame->corners[i].y + 
sozi_frame_line_width;
+       }
+    }
+
+    title_pos = sozi_frame->corners[0];
+    title_pos.y += text_get_ascent(sozi_frame->title);
+    text_set_position(sozi_frame->title, &title_pos);
+    text_calc_boundingbox(sozi_frame->title, &title_bb);
+    rectangle_union(&dia_object->bounding_box, &title_bb);
+
+    dia_object->enclosing_box = dia_object->bounding_box;
+}
+
+/******************************************************************************
+ * 
+ *****************************************************************************/
+static DiaObject * 
+sozi_frame_create(Point *startpoint,
+                 void *user_data,
+                 Handle **handle1,
+                 Handle **handle2)
+{
+    SoziFrame *sozi_frame;
+
+    sozi_frame = g_new0(SoziFrame, 1);
+
+    sozi_frame_init(sozi_frame, startpoint);
+
+    sozi_frame_update_data(sozi_frame);
+
+    *handle1 = NULL;
+    *handle2 = NULL;
+
+    return &sozi_frame->object;
+}
+
+/******************************************************************************
+ * 
+ *****************************************************************************/
+static DiaObject * 
+sozi_frame_load(ObjectNode obj_node, int version, const char *filename)
+{
+    return object_load_using_properties(&sozi_frame_type, obj_node, version, 
filename);
+}
+
+/******************************************************************************
+ * 
+ *****************************************************************************/
+static void 
+sozi_frame_save(SoziFrame *sozi_frame, ObjectNode obj_node, const char 
*filename)
+{
+    object_save_using_properties(&sozi_frame->object, obj_node, filename);
+}
+
+/******************************************************************************
+ * 
+ *****************************************************************************/
+static void 
+sozi_frame_destroy(SoziFrame *sozi_frame)
+{
+    int i;
+
+    text_destroy(sozi_frame->title);
+
+    object_unconnect_all(&sozi_frame->object);
+  
+    for (i = 0; i < 1; i++) {
+        if(sozi_frame->object.connections[i] != NULL) {
+           g_free(sozi_frame->object.connections[i]);
+        }
+    }
+
+    for (i = 0; i < 4; i++) {
+        if(sozi_frame->object.handles[i] != NULL) {
+           g_free(sozi_frame->object.handles[i]);
+        }
+    }
+
+    if (sozi_frame->object.connections) {
+        g_free(sozi_frame->object.connections);
+        sozi_frame->object.connections = NULL;
+    }
+
+    if (sozi_frame->object.handles) {
+        g_free(sozi_frame->object.handles);
+        sozi_frame->object.handles = NULL;
+    }
+
+    if (sozi_frame->object.meta) {
+        g_hash_table_destroy (sozi_frame->object.meta);
+        sozi_frame->object.meta = NULL;
+    }
+}
+
+/******************************************************************************
+ * 
+ *****************************************************************************/
+
+static int 
+find_sozi_elem(xmlDocPtr doc, const xmlChar *sozi_elem)
+{
+    /* static const xmlChar *sozi_elem = (xmlChar*) 
"//script[@id='sozi-script']"; */
+    xmlXPathContextPtr context;
+    xmlXPathObjectPtr result;
+
+    context = xmlXPathNewContext(doc);
+    if(context == NULL) {
+       fprintf(stderr, "Error in xmlXPathNewContext\n");
+       return 0;
+    }
+
+    result = xmlXPathEvalExpression(sozi_elem, context);
+    xmlXPathFreeContext(context);
+    if(result == NULL) {
+       fprintf(stderr, "Error in xmlXPathEvalExpression\n");
+       return 0;
+    }
+
+    if(xmlXPathNodeSetIsEmpty(result->nodesetval)) {
+       xmlXPathFreeObject(result);
+       return 0;
+    }
+
+    xmlXPathFreeObject(result);
+    return 1;
+}
+
+static void 
+sozi_frame_draw_svg(SoziFrame *sozi_frame, DiaSvgRenderer *svg_renderer)
+{
+    static xmlNs *sozi_name_space = NULL;
+    static unsigned refid_cnt = 0;
+    xmlNodePtr root;
+    xmlNodePtr node;
+    xmlChar * escaped;
+    /* buffers for storing attributes */
+    gchar * refid;
+    gchar * sequence;
+    gchar * x;
+    gchar * y;
+    gchar * width;
+    gchar * height;
+    gchar * transform;
+    gchar * style;
+    gchar dtostr_buf[6][G_ASCII_DTOSTR_BUF_SIZE];
+#   define dtostr(n,d) g_ascii_formatd(dtostr_buf[n], sizeof(dtostr_buf[n]), 
"%g", (d))
+
+    root = xmlDocGetRootElement(svg_renderer->doc);
+
+    /* check that the sozi namespace, scripts and style are present */
+
+    if (!find_sozi_elem(svg_renderer->doc, (const xmlChar*) 
"//script[@id='sozi-script']")) {
+
+       sozi_name_space = xmlNewNs(root, (const xmlChar 
*)"http://sozi.baierouge.fr";, (const xmlChar *)"sozi");
+
+       node = xmlNewChild(root, NULL, (const xmlChar *)"script", NULL);
+       xmlSetProp(node, (const xmlChar *)"id", (const xmlChar *)"sozi-script");
+       xmlSetProp(node, (const xmlChar *)"sozi:version", (const xmlChar 
*)sozi_version);
+       escaped = xmlEncodeEntitiesReentrant(svg_renderer->doc, (const xmlChar 
*)sozi_js);
+       xmlNodeSetContent(node, escaped);
+       xmlFree(escaped);
+
+       node = xmlNewChild(root, NULL, (const xmlChar *)"style", NULL);
+       xmlSetProp(node, (const xmlChar *)"id", (const xmlChar *)"sozi-style");
+       xmlSetProp(node, (const xmlChar *)"sozi:version", (const xmlChar 
*)sozi_version);
+       escaped = xmlEncodeEntitiesReentrant(svg_renderer->doc, (const xmlChar 
*)sozi_css);
+       xmlNodeSetContent(node, escaped);
+       xmlFree(escaped);
+    }
+
+    assert(sozi_name_space != NULL);
+
+    /* format attributes */ 
+    refid     = g_strdup_printf("sozi_frame_%d", refid_cnt++);
+    sequence  = g_strdup_printf("%d", sozi_frame->sequence);
+
+#if 1 /* pure transformation */
+
+    x         = g_strdup_printf("0");
+    y         = g_strdup_printf("0");
+    width     = g_strdup_printf("1");
+    height    = g_strdup_printf("1");
+    transform = g_strdup_printf("matrix(%s,%s,%s,%s,%s,%s)",
+                               dtostr(0, sozi_frame->m[0] * 
svg_renderer->scale),
+                               dtostr(1, sozi_frame->m[3] * 
svg_renderer->scale),
+                               dtostr(2, sozi_frame->m[1] * 
svg_renderer->scale),
+                               dtostr(3, sozi_frame->m[4] * 
svg_renderer->scale),
+                               dtostr(4, sozi_frame->m[2] * 
svg_renderer->scale),
+                               dtostr(5, sozi_frame->m[5] * 
svg_renderer->scale));
+    /* FIXME : Scaling problem on stroke width : 
http://dev.w3.org/SVG/modules/vectoreffects/master/SVGVectorEffects.html */
+    style     = g_strdup_printf("fill:none;stroke:#000000;stroke-width:%s", 
+                               dtostr(0, 0.1 / svg_renderer->scale));
+
+#elif 0 /* decompose transformation */
+
+    x         = g_strdup_printf("0");
+    y         = g_strdup_printf("0");
+    width     = g_strdup_printf("1");
+    height    = g_strdup_printf("1");
+    transform = 
g_strdup_printf("scale(%s,%s),translate(%s,%s),rotate(%s),scale(%s,%s),translate(-0.5,-0.5)",
 
+                               dtostr(0, svg_renderer->scale),
+                               dtostr(1, svg_renderer->scale),
+                               dtostr(2, sozi_frame->center.x),
+                               dtostr(3, sozi_frame->center.y),
+                               dtostr(4, 180 * sozi_frame->angle / M_PI),
+                               dtostr(5, sozi_frame->width),
+                               dtostr(6, sozi_frame->height));
+    /* FIXME : Scaling problem on stroke width : 
http://dev.w3.org/SVG/modules/vectoreffects/master/SVGVectorEffects.html */
+    style     = g_strdup_printf("fill:none;stroke:#000000;stroke-width:%s", 
+                               dtostr(0, 0.1 / svg_renderer->scale));
+
+#else /* no apply scale to transformation */
+
+    x         = g_strdup_printf("%s", dtostr(0, sozi_frame->m[2] * 
svg_renderer->scale));
+    y         = g_strdup_printf("%s", dtostr(0, sozi_frame->m[5] * 
svg_renderer->scale));
+    width     = g_strdup_printf("%s", dtostr(0, sozi_frame->width * 
svg_renderer->scale));
+    height    = g_strdup_printf("%s", dtostr(0, sozi_frame->height * 
svg_renderer->scale));
+    transform = g_strdup_printf("rotate(%s,%s,%s)", 
+                               dtostr(0, 180 * sozi_frame->angle / M_PI),
+                               dtostr(1, sozi_frame->m[2] * 
svg_renderer->scale),
+                               dtostr(2, sozi_frame->m[5] * 
svg_renderer->scale));
+
+    style     = g_strdup_printf("fill:none;stroke:#000000;stroke-width:0.1");
+
+#endif
+
+    /* add a "classic" frame */
+
+    node = xmlNewChild(svg_renderer->root, svg_renderer->svg_name_space, 
(const xmlChar *)"rect", NULL);
+
+    xmlSetProp(node, (const xmlChar *)"id"       , (xmlChar *)refid);
+    xmlSetProp(node, (const xmlChar *)"x"        , (xmlChar *)x);
+    xmlSetProp(node, (const xmlChar *)"y"        , (xmlChar *)y);
+    xmlSetProp(node, (const xmlChar *)"width"    , (xmlChar *)width);
+    xmlSetProp(node, (const xmlChar *)"height"   , (xmlChar *)height);
+    xmlSetProp(node, (const xmlChar *)"transform", (xmlChar *)transform);
+    xmlSetProp(node, (const xmlChar *)"style"    , (xmlChar *)style);
+
+    /* add a "custom" frame for sozi */
+
+    node = xmlNewChild(root, sozi_name_space, (const xmlChar *)"frame", NULL);
+    xmlSetProp(node, (const xmlChar *)"sozi:refid"                  , (const 
xmlChar *)refid);
+    xmlSetProp(node, (const xmlChar *)"sozi:sequence"               , (const 
xmlChar *)sequence);
+    xmlSetProp(node, (const xmlChar *)"sozi:title"                  , (const 
xmlChar *)text_get_line(sozi_frame->title, 0));
+    xmlSetProp(node, (const xmlChar *)"sozi:hide"                   , (const 
xmlChar *)((sozi_frame->hide)?"true":"false"));
+    xmlSetProp(node, (const xmlChar *)"sozi:clip"                   , (const 
xmlChar *)((sozi_frame->clip)?"true":"false"));
+    xmlSetProp(node, (const xmlChar *)"sozi:timeout-enable"         , (const 
xmlChar *)((sozi_frame->timeout)?"true":"false"));
+    xmlSetProp(node, (const xmlChar *)"sozi:timeout-ms"             , (const 
xmlChar *)"5000");
+    xmlSetProp(node, (const xmlChar *)"sozi:transition-profile"     , (const 
xmlChar *)"linear");
+    xmlSetProp(node, (const xmlChar *)"sozi:transition-zoom-percent", (const 
xmlChar *)"0");
+    xmlSetProp(node, (const xmlChar *)"sozi:transition-duration-ms" , (const 
xmlChar *)"1000");
+
+
+    /* free resources */
+    g_free(refid);
+    g_free(sequence);
+    g_free(x);
+    g_free(y);
+    g_free(width);
+    g_free(height);
+    g_free(transform);
+    g_free(style);
+
+#   undef dtostr
+}
+
+/******************************************************************************
+ * 
+ *****************************************************************************/
+
+#define DIA_IS_INTERACTIVE_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), 
DIA_TYPE_INTERACTIVE_RENDERER))
+
+static void 
+sozi_frame_draw(SoziFrame *sozi_frame, DiaRenderer *renderer)
+{
+    
+    if (DIA_IS_SVG_RENDERER(renderer)) {
+       sozi_frame_draw_svg(sozi_frame, DIA_SVG_RENDERER (renderer));
+    }
+    else if(DIA_GET_INTERACTIVE_RENDERER_INTERFACE (renderer) ||
+            !sozi_frame->hide) {
+       DiaRendererClass *renderer_ops = DIA_RENDERER_GET_CLASS (renderer);
+    
+       renderer_ops->set_linewidth(renderer, sozi_frame_line_width);
+        renderer_ops->set_linecaps(renderer, LINECAPS_BUTT);
+        renderer_ops->set_linejoin(renderer, LINEJOIN_MITER);
+        renderer_ops->set_linestyle(renderer, LINESTYLE_SOLID);
+
+       renderer_ops->draw_polygon(renderer, sozi_frame->corners, 4, 
&color_black);
+
+        text_draw(sozi_frame->title, renderer);
+    }
+}
+
+/******************************************************************************
+ * 
+ *****************************************************************************/
+
+static real 
+sozi_frame_distance_from(SoziFrame *sozi_frame, Point *point)
+{
+    return distance_polygon_point(sozi_frame->corners, 4, 
sozi_frame_line_width, point);
+}
+
+/******************************************************************************
+ * 
+ *****************************************************************************/
+
+static void 
+sozi_frame_select(SoziFrame *sozi_frame, Point *clicked_point,
+                 DiaRenderer *interactive_renderer)
+{
+    text_set_cursor(sozi_frame->title, clicked_point, interactive_renderer);
+    text_grab_focus(sozi_frame->title, &sozi_frame->object);
+    sozi_frame_update_data(sozi_frame);
+}
+
+/******************************************************************************
+ * 
+ *****************************************************************************/
+
+static DiaObject * 
+sozi_frame_copy(SoziFrame *sozi_frame)
+{
+    SoziFrame *new_sozi_frame;
+
+    new_sozi_frame = g_new0(SoziFrame, 1);
+
+    sozi_frame_init(new_sozi_frame, &sozi_frame->center);
+
+    new_sozi_frame->width = sozi_frame->width;
+    new_sozi_frame->height = sozi_frame->height;
+    new_sozi_frame->angle = sozi_frame->angle;
+
+    new_sozi_frame->hide = sozi_frame->hide;
+    new_sozi_frame->clip = sozi_frame->clip;
+    new_sozi_frame->timeout = sozi_frame->timeout;
+
+    sozi_frame_update_data(new_sozi_frame);
+
+    return &new_sozi_frame->object;
+}
+
+/******************************************************************************
+ * 
+ *****************************************************************************/
+
+static ObjectChange* 
+sozi_frame_move(SoziFrame *sozi_frame, Point *to)
+{
+    sozi_frame->center = *to;
+
+    sozi_frame_update_data(sozi_frame);
+
+    return NULL;
+}
+
+/******************************************************************************
+ * 
+ *****************************************************************************/
+
+static ObjectChange* 
+sozi_frame_move_handle(SoziFrame *sozi_frame, Handle *handle,
+                      Point *to, ConnectionPoint *cp,
+                      HandleMoveReason reason, ModifierKeys modifiers)
+{
+    if(reason == HANDLE_MOVE_USER) {
+       DiaObject * dia_object = &sozi_frame->object;
+       Point p2;
+
+       int i;
+       for(i = 0; i < 4; i++) {
+           if(dia_object->handles[i] == handle) {
+               break;
+           }
+       }
+       assert(i < 4);
+
+       p2 = *to;
+       point_sub(&p2, &sozi_frame->center);
+    
+       if(modifiers & MODIFIER_SHIFT) {
+           Point p1;
+           p1 = handle->pos;
+           point_sub(&p1, &sozi_frame->center);
+    
+           sozi_frame->angle += atan2(p2.x * p1.y - p2.y * p1.x, p2.x * p1.x + 
p2.y * p1.y);
+       }
+       else
+       {
+            /* the y axis is downward */ 
+           sozi_frame->width  = 2 * fabs(p2.x * sozi_frame->cos_angle - p2.y * 
sozi_frame->sin_angle); 
+           sozi_frame->height = 2 * fabs(p2.x * sozi_frame->sin_angle + p2.y * 
sozi_frame->cos_angle); 
+       }
+
+       sozi_frame_update_data(sozi_frame);
+    }
+
+    return NULL;
+}
+
+/******************************************************************************
+ * 
+ *****************************************************************************/
+
+static PropDescription sozi_frame_props[] = 
+{
+    PROP_STD_NOTEBOOK_BEGIN,
+
+    PROP_NOTEBOOK_PAGE("geometry",0,N_("Geometry")),
+    { "x"     , PROP_TYPE_REAL , PROP_FLAG_VISIBLE, N_("Position x")  , NULL, 
NULL },
+    { "y"     , PROP_TYPE_REAL , PROP_FLAG_VISIBLE, N_("Position y")  , NULL, 
NULL },
+    { "width" , PROP_TYPE_REAL , PROP_FLAG_VISIBLE, N_("Width")       , NULL, 
NULL },
+    { "height", PROP_TYPE_REAL , PROP_FLAG_VISIBLE, N_("Height")      , NULL, 
NULL },
+    { "angle" , PROP_TYPE_REAL , PROP_FLAG_VISIBLE, N_("Angle (rad)") , NULL, 
NULL },
+
+    PROP_NOTEBOOK_PAGE("sozi",0,N_("Sozi")),
+    { "frame sequence", PROP_TYPE_INT   , PROP_FLAG_VISIBLE, N_("Frame 
sequence")     , NULL, NULL },
+    { "frame title"   , PROP_TYPE_TEXT  , PROP_FLAG_VISIBLE, N_("Frame title") 
       , NULL, NULL },
+    { "frame hide"    , PROP_TYPE_BOOL  , PROP_FLAG_VISIBLE, N_("Frame hide")  
       , NULL, NULL },
+    { "frame clip"    , PROP_TYPE_BOOL  , PROP_FLAG_VISIBLE, N_("Frame clip")  
       , NULL, NULL },
+    { "frame timeout" , PROP_TYPE_INT   , PROP_FLAG_VISIBLE, N_("Frame timeout 
(ms)") , NULL, NULL },
+    PROP_STD_NOTEBOOK_END,
+
+    PROP_DESC_END
+};
+
+static PropOffset sozi_frame_offsets[] = 
+{
+    PROP_OFFSET_STD_NOTEBOOK_BEGIN,
+
+    PROP_OFFSET_NOTEBOOK_PAGE("geometry"),
+    { "x"     , PROP_TYPE_REAL ,  offsetof(SoziFrame, center.x)   },
+    { "y"     , PROP_TYPE_REAL ,  offsetof(SoziFrame, center.y)   },
+    { "width" , PROP_TYPE_REAL ,  offsetof(SoziFrame, width)      },
+    { "height", PROP_TYPE_REAL ,  offsetof(SoziFrame, height)     },
+    { "angle" , PROP_TYPE_REAL ,  offsetof(SoziFrame, angle)      },
+
+    PROP_OFFSET_NOTEBOOK_PAGE("sozi"),
+    { "frame sequence"       , PROP_TYPE_INT          , offsetof(SoziFrame, 
sequence)  },
+    { "frame title"          , PROP_TYPE_TEXT         , offsetof(SoziFrame, 
title)     },
+    { "frame hide"           , PROP_TYPE_BOOL         , offsetof(SoziFrame, 
hide)      },
+    { "frame clip"           , PROP_TYPE_BOOL         , offsetof(SoziFrame, 
clip)      },
+    { "frame timeout"        , PROP_TYPE_INT          , offsetof(SoziFrame, 
timeout)   },
+
+    PROP_OFFSET_STD_NOTEBOOK_END,
+
+    { NULL, 0, 0 }
+};
+
+static PropDescription * 
+sozi_frame_describe_props(SoziFrame *sozi_frame)
+{
+    if (sozi_frame_props[0].quark == 0)
+       prop_desc_list_calculate_quarks(sozi_frame_props);
+    return sozi_frame_props;
+}
+
+static void 
+sozi_frame_get_props(SoziFrame *sozi_frame, GPtrArray *props)
+{
+    object_get_props_from_offsets(&sozi_frame->object, sozi_frame_offsets, 
props);
+}
+
+static void 
+sozi_frame_set_props(SoziFrame *sozi_frame, GPtrArray *props)
+{
+    object_set_props_from_offsets(&sozi_frame->object, sozi_frame_offsets, 
props);
+    sozi_frame_update_data(sozi_frame);
+}
+
+
+
+
+
diff --git a/objects/Misc/sozi.h b/objects/Misc/sozi.h
new file mode 100644
index 0000000..3132742
--- /dev/null
+++ b/objects/Misc/sozi.h
@@ -0,0 +1,222 @@
+#ifndef __sozi_h__
+#define __sozi_h__
+
+static const char sozi_version[] =
+"11.09-12231119";
+
+static const char sozi_js[] =
+"var sozi=sozi||{};(function(){var 
a=sozi.events=sozi.events||{},b={};a.listen=fu"
+"nction(d,e){var c=b[d];if(!c){c=b[d]=[]}c.push(e)};a.fire=function(g){var 
d=b[g]"
+",c,f,e=Array.prototype.slice.call(arguments,1);if(d){c=d.length;for(f=0;f<c;f+=1"
+"){d[f].apply(null,e)}}}}());var sozi=sozi||{};(function(){var 
w=sozi.framelist=s"
+"ozi.framelist||{},k=this,r=k.document,q,m,c,j=0,d=5,i,u,b,y,z,v,f=300,g=\"deceler"
+"ate\",a=\"http://www.w3.org/2000/svg\";function h(A){return 
function(B){sozi.player"
+".previewFrame(A);B.stopPropagation()}}function 
l(A){A.stopPropagation()}function"
+" p(B){var 
A=B.relatedTarget;while(A!==m&&A!==q){A=A.parentNode}if(A===q){w.hide("
+");sozi.player.restart();B.stopPropagation()}}function t(B){var 
A=c.getCTM().f;if"
+"(A<=-k.innerHeight/2){A+=k.innerHeight/2}else{if(A<0){A=0}}c.setAttribute(\"trans"
+"form\",\"translate(0,\"+A+\")\");B.stopPropagation()}function e(B){var 
A=c.getCTM().f"
+";if(A+j>=k.innerHeight*3/2){A-=k.innerHeight/2}else{if(A+j>k.innerHeight+2*d){A="
+"k.innerHeight-j-4*d}}c.setAttribute(\"transform\",\"translate(0,\"+A+\")\");B.stopProp"
+"agation()}function s(A){var 
C=sozi.animation.profiles[g](A),B=1-C;z=y*C+b*B;m.se"
+"tAttribute(\"transform\",\"translate(\"+z+\",0)\")}function x(){}function 
o(){var G=r."
+"createElementNS(a,\"rect\"),A=r.createElementNS(a,\"path\"),E=r.createElementNS(a,\"p"
+"ath\"),H=0,F,C=sozi.document.frames.length,B=sozi.location.getFrameIndex(),D,I;q="
+"r.documentElement;m=r.createElementNS(a,\"g\");m.setAttribute(\"id\",\"sozi-toc\");q.a"
+"ppendChild(m);c=r.createElementNS(a,\"g\");m.appendChild(c);G.setAttribute(\"id\",\"s"
+"ozi-toc-background\");G.setAttribute(\"x\",d);G.setAttribute(\"y\",d);G.setAttribute("
+"\"rx\",d);G.setAttribute(\"ry\",d);G.addEventListener(\"click\",l,false);G.addEventLis"
+"tener(\"mousedown\",l,false);G.addEventListener(\"mouseout\",p,false);c.appendChild("
+"G);for(D=0;D<C;D+=1){I=r.createElementNS(a,\"text\");I.appendChild(r.createTextNod"
+"e(sozi.document.frames[D].title));c.appendChild(I);if(D===B){I.setAttribute(\"cla"
+"ss\",\"sozi-toc-current\")}F=I.getBBox().width;j+=I.getBBox().height;if(F>H){H=F}I."
+"setAttribute(\"x\",2*d);I.setAttribute(\"y\",j+d);I.addEventListener(\"click\",h(D),fa"
+"lse);I.addEventListener(\"mousedown\",l,false)}A.setAttribute(\"class\",\"sozi-toc-ar"
+"row\");A.setAttribute(\"d\",\"M\"+(H+3*d)+\",\"+(5*d)+\" l\"+(4*d)+\",0 
l-\"+(2*d)+\",-\"+(3*"
+"d)+\" 
z\");A.addEventListener(\"click\",t,false);A.addEventListener(\"mousedown\",l,fa"
+"lse);m.appendChild(A);E.setAttribute(\"class\",\"sozi-toc-arrow\");E.setAttribute(\"d"
+"\",\"M\"+(H+3*d)+\",\"+(7*d)+\" l\"+(4*d)+\",0 l-\"+(2*d)+\",\"+(3*d)+\" 
z\");E.addEventListe"
+"ner(\"click\",e,false);E.addEventListener(\"mousedown\",l,false);m.appendChild(E);G."
+"setAttribute(\"width\",H+7*d);G.setAttribute(\"height\",j+2*d);i=-H-9*d;u=0;z=y=i;m."
+"setAttribute(\"transform\",\"translate(\"+i+\",0)\");v=new 
sozi.animation.Animator(s,x"
+")}function n(A){var 
D=r.getElementsByClassName(\"sozi-toc-current\"),C=c.getElemen"
+"tsByTagName(\"text\"),B;for(B=0;B<D.length;B+=1){D[B].removeAttribute(\"class\")}C[A"
+"].setAttribute(\"class\",\"sozi-toc-current\")}w.show=function(){b=z;y=u;v.start(f)}"
+";w.hide=function(){b=z;y=i;v.start(f)};w.isVisible=function(){return 
y===u};sozi"
+".events.listen(\"displayready\",o);sozi.events.listen(\"cleanup\",w.hide);sozi.event"
+"s.listen(\"framechange\",n)}());var sozi=sozi||{};(function(){var 
t=sozi.player=so"
+"zi.player||{},u=sozi.display=sozi.display||{},j=this,o=j.document,p=0,v=1,s=1.05"
+",x=5,c=false,l=false,g=0,e=0;function 
a(A,z,B){t.stop();u.zoom(A>0?s:1/s,z,B)}fu"
+"nction w(y){t.stop();u.rotate(y>0?x:-x)}function 
r(){if(sozi.framelist.isVisible"
+"()){sozi.framelist.hide();t.restart()}else{t.stop();sozi.framelist.show()}}funct"
+"ion 
i(y){if(y.button===p){c=true;l=false;g=y.clientX;e=y.clientY}else{if(y.butto"
+"n===v){r()}}y.stopPropagation()}function 
m(y){if(c){t.stop();l=true;sozi.events."
+"fire(\"cleanup\");u.drag(y.clientX-g,y.clientY-e);g=y.clientX;e=y.clientY}y.stopPr"
+"opagation()}function 
f(y){if(y.button===p){c=false}y.stopPropagation()}function "
+"q(y){t.moveToPrevious();y.stopPropagation();y.preventDefault()}function 
h(y){if("
+"!l&&y.button!==v){t.moveToNext()}y.stopPropagation()}function k(y){var 
z=0;if(!y"
+"){y=j.event}if(y.wheelDelta){z=y.wheelDelta;if(j.opera){z=-z}}else{if(y.detail){"
+"z=-y.detail}}if(z!==0){if(y.shiftKey){w(z)}else{a(z,y.clientX,y.clientY)}}y.stop"
+"Propagation();y.preventDefault()}function n(y){switch(y.charCode){case 
43:a(1,j."
+"innerWidth/2,j.innerHeight/2);break;case 
45:a(-1,j.innerWidth/2,j.innerHeight/2)"
+";break;case 61:t.moveToCurrent();break;case 70:case 
102:t.showAll();break;case 8"
+"4:case 116:r();break;case 82:w(-1);break;case 
114:w(1);break}y.stopPropagation()"
+"}function d(y){switch(y.keyCode){case 36:t.moveToFirst();break;case 
35:t.moveToL"
+"ast();break;case 38:t.jumpToPrevious();break;case 33:case 
37:t.moveToPrevious();"
+"break;case 40:t.jumpToNext();break;case 34:case 39:case 13:case 
32:t.moveToNext("
+");break}y.stopPropagation()}function b(){var 
y=o.documentElement;y.addEventListe"
+"ner(\"click\",h,false);y.addEventListener(\"mousedown\",i,false);y.addEventListener("
+"\"mouseup\",f,false);y.addEventListener(\"mousemove\",m,false);y.addEventListener(\"k"
+"eypress\",n,false);y.addEventListener(\"keydown\",d,false);y.addEventListener(\"cont"
+"extmenu\",q,false);y.addEventListener(\"DOMMouseScroll\",k,false);j.onmousewheel=k}"
+"j.addEventListener(\"load\",b,false)}());var sozi=sozi||{};(function(){var 
e=sozi."
+"animation=sozi.animation||{},h=this,j=40,d=[],b,i=h.mozRequestAnimationFrame||h."
+"webkitRequestAnimationFrame||h.msRequestAnimationFrame||h.oRequestAnimationFrame"
+";function 
c(){if(i){i(f)}else{b=h.setInterval(function(){f(Date.now())},j)}}func"
+"tion f(l){var 
k;if(d.length>0){if(i){i(f)}for(k=0;k<d.length;k+=1){d[k].step(l)}"
+"}else{if(!i){h.clearInterval(b)}}}function 
a(k){d.push(k);if(d.length===1){c()}}"
+"function 
g(k){d.splice(d.indexOf(k),1)}e.Animator=function(k,l){this.onStep=k;th"
+"is.onDone=l;this.durationMs=0;this.data={};this.initialTime=0;this.started=false"
+"};e.Animator.prototype.start=function(k,l){this.durationMs=k;this.data=l;this.in"
+"itialTime=Date.now();this.onStep(0,this.data);if(!this.started){this.started=tru"
+"e;a(this)}};e.Animator.prototype.stop=function(){if(this.started){g(this);this.s"
+"tarted=false}};e.Animator.prototype.step=function(l){var 
k=l-this.initialTime;if"
+"(k>=this.durationMs){this.stop();this.onStep(1,this.data);this.onDone()}else{thi"
+"s.onStep(k/this.durationMs,this.data)}};e.profiles={linear:function(k){return 
k}"
+",accelerate:function(k){return 
Math.pow(k,3)},\"strong-accelerate\":function(k){re"
+"turn Math.pow(k,5)},decelerate:function(k){return 
1-Math.pow(1-k,3)},\"strong-dec"
+"elerate\":function(k){return 
1-Math.pow(1-k,5)},\"accelerate-decelerate\":function("
+"k){var l=k<=0.5?k:1-k,m=Math.pow(2*l,3)/2;return 
k<=0.5?m:1-m},\"strong-accelerat"
+"e-decelerate\":function(k){var l=k<=0.5?k:1-k,m=Math.pow(2*l,5)/2;return 
k<=0.5?m"
+":1-m},\"decelerate-accelerate\":function(k){var 
l=k<=0.5?k:1-k,m=(1-Math.pow(1-2*l"
+",2))/2;return k<=0.5?m:1-m},\"strong-decelerate-accelerate\":function(k){var 
l=k<="
+"0.5?k:1-k,m=(1-Math.pow(1-2*l,3))/2;return k<=0.5?m:1-m}}}());var 
sozi=sozi||{};"
+"(function(){var 
d=sozi.player=sozi.player||{},j=sozi.display=sozi.display||{},h="
+"this,c,k,e=500,q=-10,l=\"linear\",g=0,n=0,o=false,p=false;function f(t,w){var 
v=1-"
+"t,u=w.profile(t),s=1-u,r,x;for(r in 
w.initialState){if(w.initialState.hasOwnProp"
+"erty(r)){if(typeof w.initialState[r]===\"number\"&&typeof 
w.finalState[r]===\"numbe"
+"r\"){j.geometry[r]=w.finalState[r]*u+w.initialState[r]*s}}}if(w.zoomWidth&&w.zoom"
+"Width.k!==0){x=t-w.zoomWidth.ts;j.geometry.width=w.zoomWidth.k*x*x+w.zoomWidth.s"
+"s}if(w.zoomHeight&&w.zoomHeight.k!==0){x=t-w.zoomHeight.ts;j.geometry.height=w.z"
+"oomHeight.k*x*x+w.zoomHeight.ss}j.clip=w.finalState.clip;j.update()}function 
i()"
+"{var 
r;if(sozi.document.frames[n].timeoutEnable){p=true;r=(n+1)%sozi.document.fr"
+"ames.length;k=h.setTimeout(function(){d.moveToFrame(r)},sozi.document.frames[n]."
+"timeoutMs)}}function 
m(){g=n;if(o){i()}}d.startFromIndex=function(r){o=true;p=fa"
+"lse;g=r;n=r;j.showFrame(sozi.document.frames[r]);i()};d.restart=function(){d.sta"
+"rtFromIndex(n)};d.stop=function(){c.stop();if(p){h.clearTimeout(k);p=false}o=fal"
+"se;g=n};function b(r,B,z){var 
C={ss:((r<0)?Math.max(B,z):Math.min(B,z))*(100-r)/"
+"100,ts:0.5,k:0},x,w,t,s,A,y;if(r!==0){x=B-z;w=B-C.ss;t=z-C.ss;if(x!==0){s=Math.s"
+"qrt(w*t);A=(w-s)/x;y=(w+s)/x;C.ts=(A>0&&A<=1)?A:y}C.k=w/C.ts/C.ts}return 
C}d.jum"
+"pToFrame=function(r){d.stop();sozi.events.fire(\"cleanup\");g=r;n=r;j.showFrame(so"
+"zi.document.frames[r]);sozi.events.fire(\"framechange\",r)};d.previewFrame=functio"
+"n(s){var 
u=sozi.document.frames[s].geometry,r,t;if(q!==0){r=b(q,j.geometry.width"
+",u.width);t=b(q,j.geometry.height,u.height)}n=s;c.start(e,{initialState:j.getCur"
+"rentGeometry(),finalState:u,profile:sozi.animation.profiles[l],zoomWidth:r,zoomH"
+"eight:t});sozi.events.fire(\"framechange\",s)};d.moveToFrame=function(t){var 
s=e,w"
+"=q,u=sozi.animation.profiles[l],r,v;if(p){h.clearTimeout(k);p=false}if(t===(n+1)"
+"%sozi.document.frames.length){s=sozi.document.frames[t].transitionDurationMs;w=s"
+"ozi.document.frames[t].transitionZoomPercent;u=sozi.document.frames[t].transitio"
+"nProfile}sozi.events.fire(\"cleanup\");if(w!==0){r=b(w,j.geometry.width,sozi.docum"
+"ent.frames[t].geometry.width);v=b(w,j.geometry.height,sozi.document.frames[t].ge"
+"ometry.height)}o=true;n=t;c.start(s,{initialState:j.getCurrentGeometry(),finalSt"
+"ate:sozi.document.frames[n].geometry,profile:u,zoomWidth:r,zoomHeight:v});sozi.e"
+"vents.fire(\"framechange\",t)};d.moveToFirst=function(){d.moveToFrame(0)};d.jumpTo"
+"Previous=function(){var 
r=n;if(!c.started||g<=n){r-=1}if(r>=0){d.jumpToFrame(r)}"
+"};d.moveToPrevious=function(){var 
r=n,s;for(r-=1;r>=0;r-=1){s=sozi.document.fram"
+"es[r];if(!s.timeoutEnable||s.timeoutMs!==0){d.moveToFrame(r);break}}};d.jumpToNe"
+"xt=function(){var 
r=n;if(!c.started||g>=n){r+=1}if(r<sozi.document.frames.length"
+"){d.jumpToFrame(r)}};d.moveToNext=function(){if(n<sozi.document.frames.length-1|"
+"|sozi.document.frames[n].timeoutEnable){d.moveToFrame((n+1)%sozi.document.frames"
+".length)}};d.moveToLast=function(){d.moveToFrame(sozi.document.frames.length-1)}"
+";d.moveToCurrent=function(){d.moveToFrame(n)};d.showAll=function(){d.stop();sozi"
+".events.fire(\"cleanup\");c.start(e,{initialState:j.getCurrentGeometry(),finalStat"
+"e:j.getDocumentGeometry(),profile:sozi.animation.profiles[l]})};function 
a(){d.s"
+"tartFromIndex(sozi.location.getFrameIndex())}c=new 
sozi.animation.Animator(f,m);"
+"sozi.events.listen(\"displayready\",a)}());var sozi=sozi||{};(function(){var 
d=soz"
+"i.display=sozi.display||{},h=this,i=h.document,j,c,k,a,g=\"http://www.w3.org/2000";
+"/svg\";d.geometry={cx:0,cy:0,width:1,height:1,rotate:0,clip:true};function 
f(){va"
+"r 
o,l=i.createElementNS(g,\"g\"),m=i.createElementNS(g,\"clipPath\");j=i.documentEle"
+"ment;k=j.getBBox();a=i.createElementNS(g,\"g\");while(true){o=j.firstChild;if(!o){"
+"break}j.removeChild(o);a.appendChild(o)}c=i.createElementNS(g,\"rect\");c.setAttri"
+"bute(\"id\",\"sozi-clip-rect\");m.setAttribute(\"id\",\"sozi-clip-path\");m.appendChild("
+"c);j.appendChild(m);l.setAttribute(\"clip-path\",\"url(#sozi-clip-path)\");l.appendC"
+"hild(a);j.appendChild(l);j.setAttribute(\"width\",h.innerWidth);j.setAttribute(\"he"
+"ight\",h.innerHeight);sozi.events.fire(\"displayready\")}function 
b(){j.setAttribut"
+"e(\"width\",h.innerWidth);j.setAttribute(\"height\",h.innerHeight);d.update()}functi"
+"on e(){var 
l={};l.scale=Math.min(h.innerWidth/d.geometry.width,h.innerHeight/d.g"
+"eometry.height);l.width=d.geometry.width*l.scale;l.height=d.geometry.height*l.sc"
+"ale;l.x=(h.innerWidth-l.width)/2;l.y=(h.innerHeight-l.height)/2;return 
l}d.getEl"
+"ementGeometry=function(l){var 
s,p,t,n,q,o,r=l.getCTM(),m=Math.sqrt(r.a*r.a+r.b*r"
+".b);if(l.nodeName===\"rect\"){s=l.x.baseVal.value;p=l.y.baseVal.value;t=l.width.ba"
+"seVal.value;n=l.height.baseVal.value}else{q=l.getBBox();s=q.x;p=q.y;t=q.width;n="
+"q.height}o=i.documentElement.createSVGPoint();o.x=s+t/2;o.y=p+n/2;o=o.matrixTran"
+"sform(r);return{cx:o.x,cy:o.y,width:t*m,height:n*m,rotate:Math.atan2(r.b,r.a)*18"
+"0/Math.PI}};d.getDocumentGeometry=function(){return{cx:k.x+k.width/2,cy:k.y+k.he"
+"ight/2,width:k.width,height:k.height,rotate:0,clip:false}};d.getCurrentGeometry="
+"function(){return{cx:d.geometry.cx,cy:d.geometry.cy,width:d.geometry.width,heigh"
+"t:d.geometry.height,rotate:d.geometry.rotate,clip:d.geometry.clip}};d.update=fun"
+"ction(){var 
l=e(),n=-d.geometry.cx+d.geometry.width/2+l.x/l.scale,m=-d.geometry."
+"cy+d.geometry.height/2+l.y/l.scale;a.setAttribute(\"transform\",\"scale(\"+l.scale+\""
+")translate(\"+n+\",\"+m+\")rotate(\"+(-d.geometry.rotate)+\",\"+d.geometry.cx+\",\"+d.geo"
+"metry.cy+\")\");c.setAttribute(\"x\",d.geometry.clip?l.x:0);c.setAttribute(\"y\",d.geo"
+"metry.clip?l.y:0);c.setAttribute(\"width\",d.geometry.clip?l.width:h.innerWidth);c"
+".setAttribute(\"height\",d.geometry.clip?l.height:h.innerHeight)};d.showFrame=func"
+"tion(m){var l;for(l in 
m.geometry){if(m.geometry.hasOwnProperty(l)){d.geometry[l"
+"]=m.geometry[l]}}d.update()};d.drag=function(m,l){var 
n=e(),o=d.geometry.rotate*"
+"Math.PI/180;d.geometry.cx-=(m*Math.cos(o)-l*Math.sin(o))/n.scale;d.geometry.cy-="
+"(m*Math.sin(o)+l*Math.cos(o))/n.scale;d.geometry.clip=false;d.update()};d.zoom=f"
+"unction(o,m,p){var 
n=(1-o)*(m-h.innerWidth/2),l=(1-o)*(p-h.innerHeight/2);d.geom"
+"etry.width/=o;d.geometry.height/=o;d.drag(n,l)};d.rotate=function(l){d.geometry."
+"rotate+=l;d.geometry.rotate%=360;d.update()};sozi.events.listen(\"documentready\","
+"f);h.addEventListener(\"resize\",b,false)}());var 
sozi=sozi||{};(function(){var c="
+"sozi.document=sozi.document||{},g=this,a=g.document,f=\"http://sozi.baierouge.fr\"";
+",d={title:\"Untitled\",sequence:\"0\",hide:\"true\",clip:\"true\",\"timeout-enable\":\"fals"
+"e\",\"timeout-ms\":\"5000\",\"transition-duration-ms\":\"1000\",\"transition-zoom-percent\""
+":\"0\",\"transition-profile\":\"linear\"};c.frames=[];function h(j,i){var 
k=j.getAttri"
+"buteNS(f,i);return k===\"\"?d[i]:k}function b(){var 
j=a.getElementsByTagNameNS(f,\""
+"frame\"),k=j.length,m,l,n;for(l=0;l<k;l+=1){m=a.getElementById(j[l].getAttributeN"
+"S(f,\"refid\"));if(m){n={geometry:sozi.display.getElementGeometry(m),title:h(j[l],"
+"\"title\"),sequence:parseInt(h(j[l],\"sequence\"),10),hide:h(j[l],\"hide\")===\"true\",t"
+"imeoutEnable:h(j[l],\"timeout-enable\")===\"true\",timeoutMs:parseInt(h(j[l],\"timeou"
+"t-ms\"),10),transitionDurationMs:parseInt(h(j[l],\"transition-duration-ms\"),10),tr"
+"ansitionZoomPercent:parseInt(h(j[l],\"transition-zoom-percent\"),10),transitionPro"
+"file:sozi.animation.profiles[h(j[l],\"transition-profile\")||\"linear\"]};if(n.hide)"
+"{m.setAttribute(\"visibility\",\"hidden\")}n.geometry.clip=h(j[l],\"clip\")===\"true\";c"
+".frames.push(n)}}c.frames.sort(function(o,i){return 
o.sequence-i.sequence})}func"
+"tion 
e(){a.documentElement.removeAttribute(\"viewBox\");b();sozi.events.fire(\"docu"
+"mentready\")}g.addEventListener(\"load\",e,false)}());var 
sozi=sozi||{};(function()"
+"{var 
a=sozi.location=sozi.location||{},e=this,c=false;a.getFrameIndex=function()"
+"{var 
g=e.location.hash?parseInt(e.location.hash.slice(1),10)-1:0;if(isNaN(g)||g<"
+"0){return 0}else{if(g>=sozi.document.frames.length){return 
sozi.document.frames."
+"length-1}else{return g}}};function f(){var 
g=a.getFrameIndex();if(!c){sozi.playe"
+"r.moveToFrame(g)}c=false}function 
d(g){c=true;e.location.hash=\"#\"+(g+1)}function"
+" 
b(){sozi.events.listen(\"framechange\",d)}e.addEventListener(\"hashchange\",f,false"
+");e.addEventListener(\"load\",b,false)}());";
+
+static const char sozi_css[] =
+"#sozi-toc 
text{fill:#eff;font-family:Verdana,sans-serif;font-size:12pt}#sozi-toc"
+" text:hover{fill:#0cf;cursor:pointer}#sozi-toc 
text.sozi-toc-current{fill:#fa4}#"
+"sozi-toc-background{stroke:#222;stroke-opacity:.1;stroke-width:10;fill:#222;fill"
+"-opacity:.9}.sozi-toc-arrow{fill:#eff;fill-opacity:.75;stroke:none}.sozi-toc-arr"
+"ow:hover{fill:#0cf}";
+
+static const char sozi_extras_addvideo_js[] =
+"this.addEventListener(\"load\",function(){var 
k=\"http://www.w3.org/2000/svg\",l=\"ht";
+"tp://sozi.baierouge.fr\",q=\"http://www.w3.org/1999/xhtml\",m=this,o=m.document,c=o";
+".getElementsByTagNameNS(l,\"video\"),d,g,e,p,a,h,f,b;function 
n(i){i.stopPropagati"
+"on()}function 
r(i,j){sozi.events.listen(\"framechange\",function(s){if(s+1===j){i."
+"play()}})}d=[];for(g=0;g<c.length;g+=1){p=c[g].parentNode;b=o.createElementNS(q,"
+"\"source\");b.setAttribute(\"type\",c[g].getAttribute(\"type\"));b.setAttribute(\"src\","
+"c[g].getAttribute(\"src\"));for(e=0;e<d.length;e+=1){if(d[e].rect===p){break}}if(e"
+"===d.length){f=o.createElementNS(q,\"video\");f.setAttribute(\"controls\",\"controls\""
+");f.setAttribute(\"width\",p.getAttribute(\"width\"));f.setAttribute(\"height\",p.getA"
+"ttribute(\"height\"));f.addEventListener(\"click\",n,false);f.addEventListener(\"cont"
+"extmenu\",n,false);h=o.createElementNS(q,\"html\");h.appendChild(f);a=o.createEleme"
+"ntNS(k,\"foreignObject\");a.setAttribute(\"x\",p.getAttribute(\"x\"));a.setAttribute(\""
+"y\",p.getAttribute(\"y\"));a.setAttribute(\"width\",p.getAttribute(\"width\"));a.setAtt"
+"ribute(\"height\",p.getAttribute(\"height\"));a.appendChild(h);p.parentNode.insertBe"
+"fore(a,p.nextSibling);if(c[g].getAttribute(\"auto\")===\"true\"){r(f,parseInt(c[g].g"
+"etAttribute(\"frame\")))}d.push({rect:c[g].parentNode,htmlVideo:f})}d[e].htmlVideo"
+".appendChild(b)}},false);";
+
+#endif /* __sozi_h__ */
diff --git a/sheets/Misc.sheet.in b/sheets/Misc.sheet.in
index 00bd80c..ca74c90 100644
--- a/sheets/Misc.sheet.in
+++ b/sheets/Misc.sheet.in
@@ -30,6 +30,9 @@
     <object name="Misc - NewGroup">
       <_description>New-style group object, for testing</_description>
     </object>
+    <object name="Misc - Sozi Frame">
+      <_description>Sozi frame, for zooming ui</_description>
+    </object>
   </contents>
 </sheet>
 
-- 
1.7.4.4

_______________________________________________
dia-list mailing list
[email protected]
http://mail.gnome.org/mailman/listinfo/dia-list
FAQ at http://live.gnome.org/Dia/Faq
Main page at http://live.gnome.org/Dia

Reply via email to