[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

Re: How to contribute



Lars Clausen <lrclause@cs.uiuc.edu> writes:

> On 30 Aug 2003, Peter Poulsen wrote:
> > Peter Poulsen <peter_poulsen@stofanet.dk> writes:
> >
> >> I have now got that hex-thing I was talking about working. I would like
> >> to contribute it to the development version if that has any interest.
> >>
> >> How is this done best? Should I send a diff file to this list, or could
> >> I get access to the cvs and then commit it? To some extend I would
> >> prefer a diff, as this is the first time I have made anything for Dia,
> >> so it would be nice if somebody would take a quick glance at it to see
> >> if I have broken anybody else's code.
> >> -- 
> >> Yours 
> >> Peter Poulsen
> >>
> > How should I contribute; can I get a login and password to the cvs, or
> > should I send the diff files here on this mailling list?
> 
> Please send them to the list, we'll take a look at them.  I don't think
> they'll go into 0.92, though, I'm about ready to put out 0.92-pre1, and
> would rather not add new features right now.
> 
Sounds like a good idea.

Ok, here it is. Should be applied by standing in the cvs co dir, and
typing pathc -p1 < <path>/hex.patch.

I know it may sound like a weird thing to make hex-grid, but I'm working
on making a sheet (or whatever it's called), inteded for creating maps
which works a lot better with hex-grids.

This is the first time I have coded for Dia or with Gtk, so I'm open to criticism.

diff -Nuar cvs-dia/.cvsignore dia/.cvsignore
--- cvs-dia/.cvsignore	1970-01-01 01:00:00.000000000 +0100
+++ dia/.cvsignore	2003-08-30 19:39:47.000000000 +0200
@@ -0,0 +1,37 @@
+.deps
+stamp-h*
+Makefile
+dia.desktop
+Makefile.in
+aclocal.m4
+autom4te*.cache
+core-translation-report
+config.cache
+config.guess
+config.h
+config.h.in
+config.log
+config.status
+config.sub
+configure
+libtool
+ltconfig
+ltmain.sh
+main
+stamp-h
+COPYING
+mkinstalldirs
+missing
+install-sh
+ABOUT-NLS
+intl
+dia.keys
+dia.keys.tmp
+dia.pot
+intltool-extract.in 
+intltool-merge.in 
+intltool-update.in
+intltool-extract
+intltool-merge
+intltool-update
+dia.desktop
diff -Nuar cvs-dia/CVS/Entries dia/CVS/Entries
--- cvs-dia/CVS/Entries	2003-08-30 19:00:41.000000000 +0200
+++ dia/CVS/Entries	2003-08-30 19:39:48.000000000 +0200
@@ -31,4 +31,13 @@
 /po-checktrans.py/1.5/Mon Aug  5 21:38:10 2002//
 /readme.win32/1.1/Sun Jan  7 02:29:38 2001//
 /todo.gtk2/1.2/Sun Jun 16 09:54:52 2002//
-D
+D/app////
+D/broken-files////
+D/doc////
+D/lib////
+D/objects////
+D/plug-ins////
+D/po////
+D/samples////
+D/shapes////
+D/sheets////
diff -Nuar cvs-dia/CVS/Entries.Log.orig dia/CVS/Entries.Log.orig
--- cvs-dia/CVS/Entries.Log.orig	2003-08-30 19:01:04.000000000 +0200
+++ dia/CVS/Entries.Log.orig	1970-01-01 01:00:00.000000000 +0100
@@ -1,10 +0,0 @@
-A D/app////
-A D/broken-files////
-A D/doc////
-A D/lib////
-A D/objects////
-A D/plug-ins////
-A D/po////
-A D/samples////
-A D/shapes////
-A D/sheets////
diff -Nuar cvs-dia/CVS/Entries.Log.rej dia/CVS/Entries.Log.rej
--- cvs-dia/CVS/Entries.Log.rej	2003-08-30 19:39:02.000000000 +0200
+++ dia/CVS/Entries.Log.rej	1970-01-01 01:00:00.000000000 +0100
@@ -1,13 +0,0 @@
-***************
-*** 0 ****
---- 1,10 ----
-+ A D/app////
-+ A D/broken-files////
-+ A D/doc////
-+ A D/lib////
-+ A D/objects////
-+ A D/plug-ins////
-+ A D/po////
-+ A D/samples////
-+ A D/shapes////
-+ A D/sheets////
diff -Nuar cvs-dia/CVS/Entries.orig dia/CVS/Entries.orig
--- cvs-dia/CVS/Entries.orig	1970-01-01 01:00:00.000000000 +0100
+++ dia/CVS/Entries.orig	2003-08-30 19:38:50.000000000 +0200
@@ -0,0 +1,34 @@
+/.cvsignore/1.11/Wed Nov 27 13:51:34 2002//
+/AUTHORS/1.24/Sun Jul 13 20:11:19 2003//
+/ChangeLog/1.1365/Thu Aug 28 07:04:23 2003//
+/HACKING/1.5/Thu Jul 11 13:54:29 2002//
+/INSTALL/1.13/Tue Feb  4 03:55:15 2003//
+/KNOWN_BUGS/1.2/Tue Aug 27 19:36:02 2002//
+/MAINTAINERS/1.2/Fri Apr 11 19:03:53 2003//
+/Makefile.am/1.38/Tue Jul 15 05:58:11 2003//
+/NEWS/1.41/Fri Mar 14 23:17:39 2003//
+/README/1.5/Sun Aug  6 05:08:36 2000//
+/RELEASE-PROCESS/1.8/Wed Feb  5 23:10:43 2003//
+/TODO/1.31/Tue Aug 27 19:36:02 2002//
+/acinclude.m4/1.6/Sat Mar  9 22:22:42 2002//
+/autogen.sh/1.12/Sun Jul  6 08:37:17 2003//
+/config.h.win32/1.16/Fri Apr 25 16:34:46 2003//
+/configure.in/1.203/Thu Aug 28 07:04:24 2003//
+/dia-diagram.png/1.3/Sat May 18 06:34:36 2002/-kb/
+/dia.1/1.4/Sun Oct 14 16:20:17 2001//
+/dia.desktop.in/1.3/Tue Jul 15 05:58:11 2003//
+/dia.keys.in/1.1/Thu Dec  9 02:19:56 1999//
+/dia.mime/1.1/Thu Dec  9 02:19:56 1999//
+/dia.spec/1.35/Fri Mar 14 23:17:39 2003//
+/dia.xpm/1.2/Tue Sep 28 19:26:38 1999//
+/dia_gnome_icon.png/1.4/Wed Jul 24 03:16:36 2002/-kb/
+/dia_gnome_icon_large.png/1.1/Wed Jul 24 03:16:36 2002/-ko/
+/dia_gnome_menu_icon.png/1.3/Sat May 18 06:34:36 2002/-kb/
+/dia_logo.png/1.3/Sat May 18 06:34:36 2002/-kb/
+/install.win32/1.1/Sun Jan  7 02:29:38 2001//
+/makefile.msc/1.3/Sat Feb  1 11:02:40 2003//
+/po-checktrans/1.5/Mon Aug  5 21:38:10 2002//
+/po-checktrans.py/1.5/Mon Aug  5 21:38:10 2002//
+/readme.win32/1.1/Sun Jan  7 02:29:38 2001//
+/todo.gtk2/1.2/Sun Jun 16 09:54:52 2002//
+D
diff -Nuar cvs-dia/app/CVS/Entries dia/app/CVS/Entries
--- cvs-dia/app/CVS/Entries	2003-08-30 19:00:43.000000000 +0200
+++ dia/app/CVS/Entries	2003-08-30 19:39:49.000000000 +0200
@@ -132,4 +132,4 @@
 /win32print.c/1.3/Sat Aug 18 15:49:49 2001//
 /win32print.h/1.1/Mon Mar 19 00:06:29 2001//
 /winmain.c/1.2/Fri Mar 23 14:29:48 2001//
-D
+D/pixmaps////
diff -Nuar cvs-dia/app/CVS/Entries.Log dia/app/CVS/Entries.Log
--- cvs-dia/app/CVS/Entries.Log	1970-01-01 01:00:00.000000000 +0100
+++ dia/app/CVS/Entries.Log	2003-08-30 19:39:49.000000000 +0200
@@ -0,0 +1 @@
+A D/pixmaps////
diff -Nuar cvs-dia/app/CVS/Entries.orig dia/app/CVS/Entries.orig
--- cvs-dia/app/CVS/Entries.orig	1970-01-01 01:00:00.000000000 +0100
+++ dia/app/CVS/Entries.orig	2003-08-30 19:39:02.000000000 +0200
@@ -0,0 +1,135 @@
+/.cvsignore/1.5/Sat Jul 28 00:14:37 2001//
+/GNOME_Dia.oaf/1.1/Mon Mar 19 15:58:08 2001//
+/Makefile.am/1.104/Sun Jul  6 08:12:23 2003//
+/app_procs.c/1.111/Sat Jul 19 16:35:27 2003//
+/app_procs.h/1.7/Mon Feb 11 00:37:06 2002//
+/authors.h/1.9/Wed Aug 20 06:41:30 2003//
+/autosave.c/1.5/Sun Jan 19 16:38:20 2003//
+/autosave.h/1.1/Wed Jul 17 02:23:13 2002//
+/color_area.c/1.16/Tue Apr 29 22:21:28 2003//
+/color_area.h/1.4/Sun Jun  9 22:15:04 2002//
+/commands.c/1.118/Mon Aug 25 18:09:32 2003//
+/commands.h/1.36/Thu Jul 31 12:16:58 2003//
+/connectionpoint_ops.c/1.12/Wed Aug 20 05:52:15 2003//
+/connectionpoint_ops.h/1.4/Sat Jun 24 14:46:58 2000//
+/create_object.c/1.28/Wed Aug 20 06:55:05 2003//
+/create_object.h/1.6/Wed Aug 20 06:55:05 2003//
+/cursor.c/1.4/Fri Jul 26 05:10:21 2002//
+/cursor.h/1.3/Fri Jul 26 05:10:21 2002//
+/cut_n_paste.c/1.4/Fri Mar 23 14:29:48 2001//
+/cut_n_paste.h/1.3/Sat Jun 24 14:46:58 2000//
+/defaults.c/1.16/Mon Jan 27 04:22:05 2003//
+/defaults.h/1.2/Sat Jun 24 14:46:58 2000//
+/dia-props.c/1.11/Thu Aug 21 20:59:37 2003//
+/dia-props.h/1.2/Mon Aug 27 19:49:19 2001//
+/dia.def/1.4/Sun Jan 19 16:38:20 2003//
+/dia.gnorba/1.3/Tue Apr 11 14:45:04 2000//
+/dia.ico/1.1/Mon Mar 19 00:06:29 2001/-kb/
+/dia.oafinfo/1.1/Wed Aug  9 08:07:57 2000//
+/dia.rc/1.1/Mon Mar 19 00:06:29 2001//
+/dia_embedd.c/1.13/Sun Jan 19 16:38:20 2003//
+/diaconv.c/1.6/Sat Jun 22 17:19:13 2002//
+/diagram.c/1.71/Thu Aug 21 20:59:37 2003//
+/diagram.h/1.32/Thu Aug 14 10:09:47 2003//
+/diagram_tree.c/1.9/Mon Jul  7 11:03:00 2003//
+/diagram_tree.h/1.3/Tue Jan  1 15:30:24 2002//
+/diagram_tree_menu.c/1.3/Sat Jul 19 16:35:27 2003//
+/diagram_tree_menu.h/1.2/Tue Jan  1 15:30:24 2002//
+/diagram_tree_menu_callbacks.c/1.3/Sat Jul 19 16:35:27 2003//
+/diagram_tree_menu_callbacks.h/1.2/Tue Jan  1 15:30:24 2002//
+/diagram_tree_window.c/1.7/Tue Apr  8 19:56:32 2003//
+/diagram_tree_window.h/1.4/Tue Apr  8 19:56:32 2003//
+/dialogs.c/1.1/Tue Apr 23 03:53:58 2002//
+/dialogs.h/1.1/Tue Apr 23 03:53:58 2002//
+/diapagelayout.c/1.15/Fri Jul 26 03:35:53 2002//
+/diapagelayout.h/1.7/Thu Jan 27 05:36:11 2000//
+/diapsft2renderer.c/1.5/Mon Aug 25 15:18:36 2003//
+/diapsft2renderer.h/1.2/Sat Dec  7 11:10:54 2002//
+/diapsrenderer.c/1.6/Wed Jan 15 19:05:32 2003//
+/diapsrenderer.h/1.4/Sat Dec  7 11:10:54 2002//
+/diaunitspinner.c/1.8/Sat Jun  8 10:52:22 2002//
+/diaunitspinner.h/1.3/Mon Oct 25 06:12:30 1999//
+/disp_callbacks.c/1.72/Thu Aug 21 18:10:46 2003//
+/disp_callbacks.h/1.9/Sat Jul 12 09:40:12 2003//
+/display.c/1.79/Thu Jul 17 19:31:23 2003//
+/display.h/1.28/Mon Jul  7 11:03:00 2003//
+/dynamic_refresh.c/1.2/Sun Jan 19 16:38:20 2003//
+/dynamic_refresh.h/1.1/Wed Sep 25 23:44:45 2002//
+/export_png.c/1.14/Thu May  1 21:28:15 2003//
+/filedlg.c/1.27/Sat Aug 23 06:28:18 2003//
+/filedlg.h/1.3/Wed Feb 21 09:26:41 2001//
+/grid.c/1.19/Thu Aug 21 20:59:37 2003//
+/grid.h/1.8/Thu Jul 17 19:31:23 2003//
+/gtkhwrapbox.c/1.4/Sat Jun  8 10:52:22 2002//
+/gtkhwrapbox.h/1.2/Sat Jun  8 10:52:22 2002//
+/gtkvwrapbox.c/1.4/Sat Jun  8 10:52:22 2002//
+/gtkvwrapbox.h/1.2/Sat Jun  8 10:52:22 2002//
+/gtkwrapbox.c/1.3/Sat Jun  8 10:52:22 2002//
+/gtkwrapbox.h/1.2/Sat Jun  8 10:52:22 2002//
+/handle_ops.c/1.7/Sun Oct  6 18:55:11 2002//
+/handle_ops.h/1.3/Sat Jun 24 14:46:58 2000//
+/interface.c/1.95/Wed Aug 20 06:55:05 2003//
+/interface.h/1.12/Thu Apr 18 17:08:22 2002//
+/layer_dialog.c/1.26/Thu Jul 17 07:12:03 2003//
+/layer_dialog.h/1.3/Sat Jun 24 14:46:58 2000//
+/lineprops_area.c/1.21/Wed Mar  5 02:57:54 2003//
+/lineprops_area.h/1.2/Sun Oct  6 18:55:11 2002//
+/linewidth_area.c/1.14/Fri Jul 18 23:00:26 2003//
+/linewidth_area.h/1.3/Sat Jun 24 14:46:58 2000//
+/load_save.c/1.58/Sat Aug 23 06:28:18 2003//
+/load_save.h/1.6/Tue Jul 16 21:28:23 2002//
+/magnify.c/1.12/Fri Aug  1 13:23:25 2003//
+/magnify.h/1.5/Thu Oct 12 17:45:07 2000//
+/main.c/1.6/Fri Mar 23 14:29:48 2001//
+/makefile.mingw/1.4/Sat Sep 28 16:22:18 2002//
+/makefile.msc/1.26/Fri Jul 18 23:00:26 2003//
+/menus.c/1.108/Thu Jul 31 12:16:58 2003//
+/menus.h/1.17/Thu Jul 31 12:16:58 2003//
+/modify_tool.c/1.43/Wed Aug 20 05:52:15 2003//
+/modify_tool.h/1.8/Thu Sep 26 14:44:53 2002//
+/object_ops.c/1.24/Thu Dec  5 23:47:52 2002//
+/object_ops.h/1.12/Thu Dec  5 23:47:52 2002//
+/pagesetup.c/1.7/Sat Feb  1 20:03:05 2003//
+/pagesetup.h/1.1/Mon Oct 25 03:17:06 1999//
+/paginate_gdiprint.cpp/1.6/Thu Aug 21 18:10:46 2003//
+/paginate_gdiprint.h/1.2/Sat Sep 28 16:22:18 2002//
+/paginate_psprint.c/1.30/Sun Feb  9 06:04:35 2003//
+/paginate_psprint.h/1.3/Mon Oct 25 06:12:30 1999//
+/persistence.c/1.7/Thu May  1 18:06:20 2003//
+/persistence.h/1.3/Tue Apr  8 22:52:03 2003//
+/pixmaps.h/1.4/Sun Nov 21 14:45:15 1999//
+/plugin-manager.c/1.10/Wed Jan 22 23:04:37 2003//
+/plugin-manager.h/1.2/Wed Feb 21 09:26:41 2001//
+/preferences.c/1.57/Wed Aug 27 14:14:49 2003//
+/preferences.h/1.25/Sat Aug 23 06:28:18 2003//
+/properties.c/1.29/Mon Aug 25 22:06:43 2003//
+/properties.h/1.5/Sat Jun 24 14:46:58 2000//
+/recent_files.c/1.12/Sun Jan 19 16:38:20 2003//
+/recent_files.h/1.2/Sat Jan 19 11:22:24 2002//
+/render_eps.c/1.67/Thu May  1 21:28:15 2003//
+/render_eps.h/1.18/Tue Oct 15 19:43:03 2002//
+/render_gdk.c/1.51/Fri Nov  8 04:50:18 2002//
+/render_gdk.h/1.8/Sun Oct  6 18:55:11 2002//
+/render_libart.c/1.39/Thu Aug 14 06:49:10 2003//
+/render_libart.h/1.10/Sun Oct  6 23:46:46 2002//
+/render_pixmap.c/1.8/Sun Oct  6 18:55:11 2002//
+/render_pixmap.h/1.4/Sun Oct  6 18:55:11 2002//
+/scroll_tool.c/1.9/Wed Aug 20 06:55:05 2003//
+/scroll_tool.h/1.4/Sat Jun 24 14:46:58 2000//
+/select.c/1.9/Wed May 16 13:35:24 2001//
+/select.h/1.3/Wed Feb 21 09:26:41 2001//
+/sheets.c/1.10/Fri Jan 31 04:34:37 2003//
+/sheets.h/1.2/Fri Apr 26 20:33:35 2002//
+/sheets_dialog.c/1.8/Tue Apr  8 19:56:32 2003//
+/sheets_dialog.h/1.1/Fri Apr 12 07:51:36 2002//
+/sheets_dialog_callbacks.c/1.16/Fri Jan 31 04:34:37 2003//
+/sheets_dialog_callbacks.h/1.2/Fri Jan 31 04:34:37 2003//
+/splash.c/1.8/Sun Dec  8 18:18:16 2002//
+/tool.c/1.9/Wed Aug 20 06:55:05 2003//
+/tool.h/1.8/Wed Aug 20 06:55:05 2003//
+/undo.c/1.18/Mon Aug 25 15:18:36 2003//
+/undo.h/1.11/Thu Aug  7 11:35:42 2003//
+/win32print.c/1.3/Sat Aug 18 15:49:49 2001//
+/win32print.h/1.1/Mon Mar 19 00:06:29 2001//
+/winmain.c/1.2/Fri Mar 23 14:29:48 2001//
+D
diff -Nuar cvs-dia/app/diagram.c dia/app/diagram.c
--- cvs-dia/app/diagram.c	2003-08-21 22:59:37.000000000 +0200
+++ dia/app/diagram.c	2003-08-30 19:39:49.000000000 +0200
@@ -58,6 +58,7 @@
   dia->data = new_diagram_data(&prefs.new_diagram);
   dia->data->grid.width_x = prefs.grid.x;
   dia->data->grid.width_y = prefs.grid.y;
+  dia->data->grid.width_w = prefs.grid.w;
   dia->data->grid.dynamic = prefs.grid.dynamic;
   dia->data->grid.major_lines = prefs.grid.major_lines;
 
diff -Nuar cvs-dia/app/diagram.c.orig dia/app/diagram.c.orig
--- cvs-dia/app/diagram.c.orig	1970-01-01 01:00:00.000000000 +0100
+++ dia/app/diagram.c.orig	2003-08-30 19:39:04.000000000 +0200
@@ -0,0 +1,1121 @@
+/* Dia -- an diagram creation/manipulation program
+ * Copyright (C) 1998 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.
+ */
+
+#include <config.h>
+
+#include <assert.h>
+#include <string.h>
+
+#include "intl.h"
+#include "diagram.h"
+#include "group.h"
+#include "object_ops.h"
+#include "render_eps.h"
+#include "focus.h"
+#include "message.h"
+#include "menus.h"
+#include "preferences.h"
+#include "properties.h"
+#include "cut_n_paste.h"
+#include "layer_dialog.h"
+#include "app_procs.h"
+#include "dia_dirs.h"
+#include "load_save.h"
+#include "recent_files.h"
+#include "diagram_tree_window.h"
+#include "autosave.h"
+#include "dynamic_refresh.h"
+
+static GList *open_diagrams = NULL;
+
+GList *
+dia_open_diagrams(void)
+{
+  return open_diagrams;
+}
+
+static void
+diagram_init(Diagram *dia, const char *filename)
+{
+  if (dia->data)
+    diagram_data_destroy(dia->data);
+  
+  dia->data = new_diagram_data(&prefs.new_diagram);
+  dia->data->grid.width_x = prefs.grid.x;
+  dia->data->grid.width_y = prefs.grid.y;
+  dia->data->grid.dynamic = prefs.grid.dynamic;
+  dia->data->grid.major_lines = prefs.grid.major_lines;
+
+  if (dia->filename != NULL)
+    g_free(dia->filename);
+  dia->filename = g_strdup(filename);
+  
+  dia->unsaved = TRUE;
+  dia->modified = FALSE;
+  dia->autosavefilename = NULL;
+
+  if (dia->undo)
+    undo_destroy(dia->undo);
+  dia->undo = new_undo_stack(dia);
+
+  if (!g_list_find(open_diagrams, dia))
+    open_diagrams = g_list_prepend(open_diagrams, dia);
+
+  layer_dialog_update_diagram_list();
+}
+
+int
+diagram_load_into(Diagram         *diagram,
+		  const char      *filename,
+		  DiaImportFilter *ifilter)
+{
+  if (!ifilter)
+    ifilter = filter_guess_import_filter(filename);
+  if (!ifilter)  /* default to native format */
+    ifilter = &dia_import_filter;
+
+  diagram_init(diagram, filename);
+
+  if (ifilter->import(filename, diagram->data, ifilter->user_data)) {
+    diagram->unsaved = FALSE;
+    diagram_set_modified(diagram, FALSE);
+    recent_file_history_add(filename, ifilter, 0);
+    diagram_tree_add(diagram_tree(), diagram);
+    return TRUE;
+  } else
+    return FALSE;
+}
+
+Diagram *
+diagram_load(const char *filename, DiaImportFilter *ifilter)
+{
+  Diagram *diagram;
+
+  diagram = new_diagram(filename);
+
+  if (!diagram_load_into (diagram, filename, ifilter)) {
+    diagram_destroy(diagram);
+    diagram = NULL;
+  }
+
+  return diagram;
+}
+
+Diagram *
+new_diagram(const char *filename)  /* Note: filename is copied */
+{
+  Diagram *dia = g_new0(Diagram, 1);
+
+  diagram_init(dia, filename);
+
+  return dia;
+}
+
+void
+diagram_destroy(Diagram *dia)
+{
+  assert(dia->displays==NULL);
+
+  diagram_data_destroy(dia->data);
+  
+  g_free(dia->filename);
+
+  open_diagrams = g_list_remove(open_diagrams, dia);
+  layer_dialog_update_diagram_list();
+
+  undo_destroy(dia->undo);
+  
+  diagram_tree_remove(diagram_tree(), dia);
+
+  diagram_cleanup_autosave(dia);
+  
+  g_free(dia);
+}
+
+void
+diagram_modified(Diagram *dia)
+{
+  diagram_set_modified(dia, TRUE);
+}
+
+void
+diagram_set_modified(Diagram *dia, int modified)
+{
+  GSList *displays;
+
+  if (dia->modified != modified)
+  {
+    dia->modified = modified;
+    displays = dia->displays;
+    while (displays != NULL)
+    {
+      DDisplay *display = (DDisplay*) displays->data;
+      ddisplay_update_statusbar(display);
+      displays = g_slist_next(displays);
+    }
+  }
+  dia->autosaved = FALSE;
+}
+
+
+/*
+  This is the real implementation of the sensitivity update.
+  TODO: move it to the DDisplay as it belongs to it IMHO
+ */
+void 
+diagram_update_menu_sensitivity (Diagram *dia, UpdatableMenuItems *items)
+{
+  gtk_widget_set_sensitive(GTK_WIDGET(items->copy),
+			   dia->data->selected_count > 0);
+  gtk_widget_set_sensitive(GTK_WIDGET(items->cut),
+			   dia->data->selected_count > 0);
+  gtk_widget_set_sensitive(GTK_WIDGET(items->paste),
+			   cnp_exist_stored_objects());
+  #ifndef GNOME
+  gtk_widget_set_sensitive(GTK_WIDGET(items->edit_delete),
+			   dia->data->selected_count > 0);
+  #endif
+    
+  gtk_widget_set_sensitive(GTK_WIDGET(items->copy_text),
+			   active_focus() != NULL);
+  gtk_widget_set_sensitive(GTK_WIDGET(items->cut_text),
+			   active_focus() != NULL);
+  gtk_widget_set_sensitive(GTK_WIDGET(items->paste_text),
+			   active_focus() != NULL);
+  
+  gtk_widget_set_sensitive(GTK_WIDGET(items->send_to_back),
+			   dia->data->selected_count > 0);
+  gtk_widget_set_sensitive(GTK_WIDGET(items->bring_to_front),
+			   dia->data->selected_count > 0);
+    
+  gtk_widget_set_sensitive(GTK_WIDGET(items->parent),
+			   (dia->data->selected_count > 1));
+  gtk_widget_set_sensitive(GTK_WIDGET(items->unparent),
+			   (dia->data->selected_count > 0));
+  gtk_widget_set_sensitive(GTK_WIDGET(items->unparent_children),
+			   (dia->data->selected_count > 0));
+  gtk_widget_set_sensitive(GTK_WIDGET(items->group),
+			   dia->data->selected_count > 1);
+  gtk_widget_set_sensitive(GTK_WIDGET(items->ungroup),
+			   (dia->data->selected_count > 0));
+  
+  gtk_widget_set_sensitive(GTK_WIDGET(items->align_h_l),
+			   dia->data->selected_count > 1);
+  gtk_widget_set_sensitive(GTK_WIDGET(items->align_h_c),
+			   dia->data->selected_count > 1);
+  gtk_widget_set_sensitive(GTK_WIDGET(items->align_h_r),
+			   dia->data->selected_count > 1);
+  gtk_widget_set_sensitive(GTK_WIDGET(items->align_h_e),
+			   dia->data->selected_count > 1);
+  gtk_widget_set_sensitive(GTK_WIDGET(items->align_h_a),
+			   dia->data->selected_count > 1);
+  gtk_widget_set_sensitive(GTK_WIDGET(items->align_v_t),
+			   dia->data->selected_count > 1);
+  gtk_widget_set_sensitive(GTK_WIDGET(items->align_v_c),
+			   dia->data->selected_count > 1);
+  gtk_widget_set_sensitive(GTK_WIDGET(items->align_v_b),
+			   dia->data->selected_count > 1);
+  gtk_widget_set_sensitive(GTK_WIDGET(items->align_v_e),
+			   dia->data->selected_count > 1);
+  gtk_widget_set_sensitive(GTK_WIDGET(items->align_v_a),
+			   dia->data->selected_count > 1);
+}
+    
+  
+void diagram_update_menubar_sensitivity(Diagram *dia, UpdatableMenuItems *items)
+{
+    diagram_update_menu_sensitivity (dia, items);
+}
+
+
+void diagram_update_popupmenu_sensitivity(Diagram *dia)
+{
+  static int initialized = 0;
+  static UpdatableMenuItems items;
+  
+
+  char *display = "<Display>";
+  
+  if (initialized==0) {
+      menus_initialize_updatable_items (&items, NULL, display);
+      
+      initialized = 1;
+  }
+  
+  diagram_update_menu_sensitivity (dia, &items);
+}
+
+void
+diagram_add_ddisplay(Diagram *dia, DDisplay *ddisp)
+{
+  dia->displays = g_slist_prepend(dia->displays, ddisp);
+  dia->display_count++;
+}
+
+void
+diagram_remove_ddisplay(Diagram *dia, DDisplay *ddisp)
+{
+  dia->displays = g_slist_remove(dia->displays, ddisp);
+  dia->display_count--;
+
+  if (dia->display_count == 0) {
+    if (!app_is_embedded()) {
+      /* Don't delete embedded diagram when last view is closed */
+      diagram_destroy(dia);
+    }
+  }
+}
+
+void
+diagram_add_object(Diagram *dia, Object *obj)
+{
+  layer_add_object(dia->data->active_layer, obj);
+
+  diagram_modified(dia);
+
+  diagram_tree_add_object(diagram_tree(), dia, obj);
+}
+
+void
+diagram_add_object_list(Diagram *dia, GList *list)
+{
+  layer_add_objects(dia->data->active_layer, list);
+
+  diagram_modified(dia);
+
+  diagram_tree_add_objects(diagram_tree(), dia, list);
+}
+
+void
+diagram_selected_break_external(Diagram *dia)
+{
+  GList *list;
+  GList *connected_list;
+  Object *obj;
+  Object *other_obj;
+  int i,j;
+
+  list = dia->data->selected;
+  while (list != NULL) {
+    obj = (Object *)list->data;
+    
+    /* Break connections between this object and objects not selected: */
+    for (i=0;i<obj->num_handles;i++) {
+      ConnectionPoint *con_point;
+      con_point = obj->handles[i]->connected_to;
+      
+      if ( con_point == NULL )
+	break; /* Not connected */
+      
+      other_obj = con_point->object;
+      if (g_list_find(dia->data->selected, other_obj) == NULL) {
+	/* other_obj is not selected, break connection */
+	Change *change = undo_unconnect(dia, obj, obj->handles[i]);
+	(change->apply)(change, dia);
+	object_add_updates(obj, dia);
+      }
+    }
+    
+    /* Break connections from non selected objects to this object: */
+    for (i=0;i<obj->num_connections;i++) {
+      connected_list = obj->connections[i]->connected;
+      
+      while (connected_list != NULL) {
+	other_obj = (Object *)connected_list->data;
+	
+	if (g_list_find(dia->data->selected, other_obj) == NULL) {
+	  /* other_obj is not in list, break all connections
+	     to obj from other_obj */
+	  
+	  for (j=0;j<other_obj->num_handles;j++) {
+	    ConnectionPoint *con_point;
+	    con_point = other_obj->handles[j]->connected_to;
+
+	    if (con_point && (con_point->object == obj)) {
+	      Change *change;
+	      connected_list = g_list_previous(connected_list);
+	      change = undo_unconnect(dia, other_obj,
+					      other_obj->handles[j]);
+	      (change->apply)(change, dia);
+	      if (connected_list == NULL)
+		connected_list = obj->connections[i]->connected;
+	    }
+	  }
+	}
+	
+	connected_list = g_list_next(connected_list);
+      }
+    }
+    diagram_tree_remove_object(diagram_tree(), obj);
+    list = g_list_next(list);
+  }
+}
+
+void
+diagram_remove_all_selected(Diagram *diagram, int delete_empty)
+{
+  object_add_updates_list(diagram->data->selected, diagram);
+	
+  data_remove_all_selected(diagram->data);
+  
+  remove_focus();
+}
+
+void
+diagram_unselect_object(Diagram *diagram, Object *obj)
+{
+  object_add_updates(obj, diagram);
+  
+  data_unselect(diagram->data, obj);
+  
+  if ((active_focus()!=NULL) && (active_focus()->obj == obj)) {
+    remove_focus();
+  }
+}
+
+void
+diagram_unselect_objects(Diagram *dia, GList *obj_list)
+{
+  GList *list;
+  Object *obj;
+
+  list = obj_list;
+  while (list != NULL) {
+    obj = (Object *) list->data;
+
+    if (g_list_find(dia->data->selected, obj) != NULL){
+      diagram_unselect_object(dia, obj);
+    }
+
+    list = g_list_next(list);
+  }
+}
+
+void
+diagram_select(Diagram *diagram, Object *obj)
+{
+  data_select(diagram->data, obj);
+  object_add_updates(obj, diagram);
+}
+
+void
+diagram_select_list(Diagram *dia, GList *list)
+{
+
+  while (list != NULL) {
+    Object *obj = (Object *)list->data;
+
+    diagram_select(dia, obj);
+
+    list = g_list_next(list);
+  }
+}
+
+int
+diagram_is_selected(Diagram *diagram, Object *obj)
+{
+  return g_list_find(diagram->data->selected, obj) != NULL;
+}
+
+void
+diagram_redraw_all()
+{
+  GList *list;
+  Diagram *dia;
+
+  list = open_diagrams;
+
+  while (list != NULL) {
+    dia = (Diagram *) list->data;
+
+    diagram_add_update_all(dia);
+    diagram_flush(dia);
+
+    list = g_list_next(list);
+  }
+  return;
+}
+
+void
+diagram_add_update_all(Diagram *dia)
+{
+  GSList *l;
+  DDisplay *ddisp;
+  
+  l = dia->displays;
+  while (l!=NULL) {
+    ddisp = (DDisplay *) l->data;
+
+    ddisplay_add_update_all(ddisp);
+    
+    l = g_slist_next(l);
+  }
+}
+
+void
+diagram_add_update(Diagram *dia, Rectangle *update)
+{
+  GSList *l;
+  DDisplay *ddisp;
+  
+  l = dia->displays;
+  while (l!=NULL) {
+    ddisp = (DDisplay *) l->data;
+
+    ddisplay_add_update(ddisp, update);
+    
+    l = g_slist_next(l);
+  }
+}
+
+void
+diagram_add_update_pixels(Diagram *dia, Point *point,
+			  int pixel_width, int pixel_height)
+{
+  GSList *l;
+  DDisplay *ddisp;
+
+  l = dia->displays;
+  while (l!=NULL) {
+    ddisp = (DDisplay *) l->data;
+
+    ddisplay_add_update_pixels(ddisp, point, pixel_width, pixel_height);
+    
+    l = g_slist_next(l);
+  }
+}
+
+void
+diagram_flush(Diagram *dia)
+{
+  GSList *l;
+  DDisplay *ddisp;
+  l = dia->displays;
+  while (l!=NULL) {
+    ddisp = (DDisplay *) l->data;
+
+    ddisplay_flush(ddisp);
+    
+    l = g_slist_next(l);
+  }
+  dynobj_refresh_kick();
+}
+
+Object *
+diagram_find_clicked_object(Diagram *dia, Point *pos,
+			    real maxdist)
+{
+  return layer_find_closest_object_except(dia->data->active_layer, 
+					  pos, maxdist, NULL);
+}
+
+Object *
+diagram_find_clicked_object_except(Diagram *dia, Point *pos,
+				   real maxdist, GList *avoid)
+{
+  return layer_find_closest_object_except(dia->data->active_layer, pos,
+					  maxdist, avoid);
+}
+
+/*
+ * Always returns the last handle in an object that has
+ * the closest distance
+ */
+real
+diagram_find_closest_handle(Diagram *dia, Handle **closest,
+			    Object **object, Point *pos)
+{
+  GList *l;
+  Object *obj;
+  Handle *handle;
+  real mindist, dist;
+  int i;
+
+  mindist = 1000000.0; /* Realy big value... */
+  
+  *closest = NULL;
+  
+  l = dia->data->selected;
+  while (l!=NULL) {
+    obj = (Object *) l->data;
+
+    for (i=0;i<obj->num_handles;i++) {
+      handle = obj->handles[i];
+      /* Note: Uses manhattan metric for speed... */
+      dist = distance_point_point_manhattan(pos, &handle->pos);
+      if (dist<=mindist) { 
+	mindist = dist;
+	*closest = handle;
+	*object = obj;
+      }
+    }
+    
+    l = g_list_next(l);
+  }
+
+  return mindist;
+}
+
+real
+diagram_find_closest_connectionpoint(Diagram *dia,
+				     ConnectionPoint **closest,
+				     Point *pos,
+				     Object *notthis)
+{
+  return layer_find_closest_connectionpoint(dia->data->active_layer,
+					    closest, pos, notthis);
+}
+
+void
+diagram_update_extents(Diagram *dia)
+{
+  gfloat cur_scale = dia->data->paper.scaling;
+  /* anropar update_scrollbars() */
+
+  if (data_update_extents(dia->data)) {
+    /* Update scrollbars because extents were changed: */
+    GSList *l;
+    DDisplay *ddisp;
+    
+    l = dia->displays;
+    while (l!=NULL) {
+      ddisp = (DDisplay *) l->data;
+      
+      ddisplay_update_scrollbars(ddisp);
+      
+      l = g_slist_next(l);
+    }
+    if (cur_scale != dia->data->paper.scaling) {
+      diagram_add_update_all(dia);
+      diagram_flush(dia);
+    }
+  }  
+}
+
+/* Remove connections from obj to objects outside created group. */
+static void
+strip_connections(Object *obj, GList *not_strip_list, Diagram *dia)
+{
+  int i;
+  Handle *handle;
+  Change *change;
+
+  for (i=0;i<obj->num_handles;i++) {
+    handle = obj->handles[i];
+    if ((handle->connected_to != NULL) &&
+	(g_list_find(not_strip_list, handle->connected_to->object)==NULL)) {
+      change = undo_unconnect(dia, obj, handle);
+      (change->apply)(change, dia);
+    }
+  }
+}
+
+
+gint diagram_parent_sort_cb(object_extent ** a, object_extent **b)
+{
+  if ((*a)->extent->left < (*b)->extent->left)
+    return 1;
+  else if ((*a)->extent->left > (*b)->extent->left)
+    return -1;
+  else
+    if ((*a)->extent->top < (*b)->extent->top)
+      return 1;
+    else if ((*a)->extent->top > (*b)->extent->top)
+      return -1;
+    else
+      return 0;
+}
+
+
+/* needs faster algorithm -- if we find that parenting is slow.
+ * If it works, don't optimize it until it's a hotspot. */
+void diagram_parent_selected(Diagram *dia)
+{
+  GList *list = dia->data->selected;
+  int length = g_list_length(list);
+  int idx, idx2;
+  object_extent *oe;
+  gboolean any_parented = FALSE;
+  GPtrArray *rects = g_ptr_array_sized_new(length);
+  while (list)
+  {
+    oe = g_new(object_extent, 1);
+    oe->object = list->data;
+    oe->extent = parent_handle_extents(list->data);
+    g_ptr_array_add(rects, oe);
+    list = g_list_next(list);
+  }
+  /* sort all the objects by its left position */
+  g_ptr_array_sort(rects, diagram_parent_sort_cb);
+
+  for (idx = 0; idx < length; idx++)
+  {
+    object_extent *rect = g_ptr_array_index(rects, idx);
+    if (rect->object->parent)
+      continue;
+
+    for (idx2 = idx + 1; idx2 < length; idx2++)
+    {
+      object_extent *rect2 = g_ptr_array_index(rects, idx2);
+      if (!rect2->object->can_parent)
+        continue;
+
+      if (rect->extent->right <= rect2->extent->right
+        && rect->extent->bottom <= rect2->extent->bottom)
+      {
+	Change *change;
+	change = undo_parenting(dia, rect2->object, rect->object, TRUE);
+	(change->apply)(change, dia);
+	any_parented = TRUE;
+	/*
+        rect->object->parent = rect2->object;
+	rect2->object->children = g_list_append(rect2->object->children, rect->object);
+	*/
+	break;
+      }
+    }
+  }
+  g_ptr_array_free(rects, TRUE);
+  if (any_parented) {
+    diagram_modified(dia);
+    diagram_flush(dia);
+    undo_set_transactionpoint(dia->undo);
+  }
+}
+
+/** Remove all selected objects from their parents (if any). */
+void diagram_unparent_selected(Diagram *dia)
+{
+  GList *list;
+  Object *obj, *parent;
+  Change *change;
+  gboolean any_unparented = FALSE;
+
+  for (list = dia->data->selected; list != NULL; list = g_list_next(list))
+  {
+    obj = (Object *) list->data;
+    parent = obj->parent;
+    
+    if (!parent)
+      continue;
+
+    change = undo_parenting(dia, parent, obj, FALSE);
+    (change->apply)(change, dia);
+    any_unparented = TRUE;
+    /*
+    parent->children = g_list_remove(parent->children, obj);
+    obj->parent = NULL;
+    */
+  }
+  if (any_unparented) {
+    diagram_modified(dia);
+    diagram_flush(dia);
+    undo_set_transactionpoint(dia->undo);
+  }
+}
+
+/** Remove all children from the selected parents. */
+void diagram_unparent_children_selected(Diagram *dia)
+{
+  GList *list;
+  GList *child_ptr;
+  Object *obj, *child;
+  gboolean any_unparented = FALSE;
+  for (list = dia->data->selected; list != NULL; list = g_list_next(list))
+  {
+    obj = (Object *) list->data;
+    if (!obj->can_parent || !obj->children)
+      continue;
+
+    any_unparented = TRUE;
+    /* Yes, this creates a whole bunch of Changes.  They're lightweight
+     * structures, though, and it's easier to assure correctness this
+     * way.  If needed, we can make a parent undo with a list of children.
+     */
+    while (obj->children != NULL) {
+      Change *change;
+      child = (Object *) obj->children->data;
+      change = undo_parenting(dia, obj, child, FALSE);
+      /* This will remove one item from the list, so the while terminates. */
+      (change->apply)(change, dia);
+    }
+    /*
+    for (child_ptr = obj->children; child_ptr != NULL; 
+	 child_ptr = g_list_next(child_ptr))
+    {
+      Change *change;
+      child = (Object *) child_ptr->data;
+      change = undo_parenting(dia, obj, child, FALSE);
+      (change->apply)(change, dia);
+    }
+    */
+    if (obj->children != NULL)
+      printf("Obj still has %d children\n",
+	     g_list_length(obj->children));
+    /*
+    g_list_free(obj->children);
+    obj->children = NULL;
+    */
+  }
+  if (any_unparented) {
+    diagram_modified(dia);
+    diagram_flush(dia);
+    undo_set_transactionpoint(dia->undo);
+  }
+}
+
+void diagram_group_selected(Diagram *dia)
+{
+  GList *list;
+  GList *group_list;
+  Object *group;
+  Object *obj;
+  GList *orig_list;
+  Change *change;
+
+  dia->data->selected = parent_list_affected(dia->data->selected);
+
+  orig_list = g_list_copy(dia->data->active_layer->objects);
+  
+  /* We have to rebuild the selection list so that it is the same
+     order as in the Diagram list. */
+  group_list = diagram_get_sorted_selected_remove(dia);
+  
+  list = group_list;
+  while (list != NULL) {
+    obj = (Object *)list->data;
+
+    /* Remove connections from obj to objects outside created group. */
+    /* strip_connections sets up its own undo info. */
+    /* The connections aren't reattached by ungroup. */
+    strip_connections(obj, dia->data->selected, dia);
+    
+    /* Have to hide any open properties dialog
+     * if it contains some object in cut_list */
+    /* Now handled by undo_apply
+    properties_hide_if_shown(dia, obj);
+    */
+
+    /* Remove focus if active */
+    /* Now handled by undo apply
+    if ((active_focus()!=NULL) && (active_focus()->obj == obj)) {
+      remove_focus();
+    }
+    */
+
+    /* Now handled by the undo apply
+    object_add_updates(obj, dia);
+    */
+    list = g_list_next(list);
+  }
+
+  /* Remove list of selected objects */
+  data_remove_all_selected(dia->data);
+  
+  group = group_create(group_list);
+  change = undo_group_objects(dia, group_list, group, orig_list);
+  (change->apply)(change, dia);
+
+  /* Select the created group */
+  diagram_select(dia, group);
+  
+  diagram_modified(dia);
+  diagram_flush(dia);
+
+  undo_set_transactionpoint(dia->undo);
+}
+
+void diagram_ungroup_selected(Diagram *dia)
+{
+  Object *group;
+  GList *group_list;
+  GList *list;
+  GList *selected;
+  int group_index;
+  int any_groups = 0;
+  
+  if (dia->data->selected_count < 1) {
+    message_error("Trying to ungroup with no selected objects.");
+    return;
+  }
+  
+  selected = dia->data->selected;
+  while (selected != NULL) {
+    group = (Object *)selected->data;
+
+    if (IS_GROUP(group)) {
+      Change *change;
+
+      /* Fix selection */
+      diagram_unselect_object(dia, group);
+
+      group_list = group_objects(group);
+      diagram_select_list(dia, group_list);
+      /* Now handled by undo apply */      
+      /*list = group_list;
+      while (list != NULL) {
+	Object *obj = (Object *)list->data;
+	object_add_updates(obj, dia);
+	list = g_list_next(list);
+      }
+      */
+
+      /* Now handled by undo apply
+      layer_replace_object_with_list(dia->data->active_layer,
+				     group, g_list_copy(group_list));
+      */
+
+      group_index = layer_object_index(dia->data->active_layer, group);
+    
+      change = undo_ungroup_objects(dia, group_list, group, group_index);
+      (change->apply)(change, dia);
+      /* Now handled by undo apply 
+      diagram_tree_add_objects(diagram_tree(), dia, group_list);
+      diagram_tree_remove_object(diagram_tree(), group);
+      properties_hide_if_shown(dia, group);
+      */
+
+      any_groups = 1;
+    }
+    selected = g_list_next(selected);
+  }
+  
+  if (any_groups) {
+    diagram_modified(dia);
+    diagram_flush(dia);
+    undo_set_transactionpoint(dia->undo);
+  }
+}
+
+GList *
+diagram_get_sorted_selected(Diagram *dia)
+{
+  return data_get_sorted_selected(dia->data);
+}
+
+/* Removes selected from objects list, NOT selected list! */
+GList *
+diagram_get_sorted_selected_remove(Diagram *dia)
+{
+  diagram_modified(dia);
+
+  return data_get_sorted_selected_remove(dia->data);
+}
+
+void
+diagram_place_under_selected(Diagram *dia)
+{
+  GList *sorted_list;
+  GList *orig_list;
+
+  if (dia->data->selected_count == 0)
+    return;
+
+  orig_list = g_list_copy(dia->data->active_layer->objects);
+
+  sorted_list = diagram_get_sorted_selected_remove(dia);
+  object_add_updates_list(sorted_list, dia);
+  layer_add_objects_first(dia->data->active_layer, sorted_list);
+  
+  undo_reorder_objects(dia, g_list_copy(sorted_list), orig_list);
+
+  diagram_modified(dia);
+  diagram_flush(dia);
+  undo_set_transactionpoint(dia->undo);
+}
+
+void
+diagram_place_over_selected(Diagram *dia)
+{
+  GList *sorted_list;
+  GList *orig_list;
+
+  if (dia->data->selected_count == 0)
+    return;
+
+  orig_list = g_list_copy(dia->data->active_layer->objects);
+  
+  sorted_list = diagram_get_sorted_selected_remove(dia);
+  object_add_updates_list(sorted_list, dia);
+  layer_add_objects(dia->data->active_layer, sorted_list);
+  
+  undo_reorder_objects(dia, g_list_copy(sorted_list), orig_list);
+
+  diagram_modified(dia);
+  diagram_flush(dia);
+  undo_set_transactionpoint(dia->undo);
+}
+
+void
+diagram_place_up_selected(Diagram *dia)
+{
+  GList *sorted_list;
+  GList *orig_list;
+  GList *tmp, *stmp;
+  GList *new_list = NULL;
+
+  if (dia->data->selected_count == 0)
+    return;
+
+  orig_list = g_list_copy(dia->data->active_layer->objects);
+  
+  sorted_list = diagram_get_sorted_selected(dia);
+  object_add_updates_list(orig_list, dia);
+
+  new_list = g_list_copy(orig_list);
+  stmp = g_list_last(sorted_list);
+
+  for (tmp = g_list_last(new_list);
+       tmp != NULL;
+       tmp = g_list_previous(tmp)) {
+    if (stmp == NULL) break;
+    if (tmp->prev == NULL) break;
+    if (tmp->data == stmp->data) {
+      stmp = g_list_previous(stmp);
+    } else if (tmp->prev->data == stmp->data) {
+      void *swap = tmp->data;
+      tmp->data = tmp->prev->data;
+      tmp->prev->data = swap;
+      stmp = g_list_previous(stmp);
+    }
+  }
+
+  layer_set_object_list(dia->data->active_layer, new_list);
+
+  undo_reorder_objects(dia, g_list_copy(sorted_list), orig_list);
+
+  diagram_modified(dia);
+  diagram_flush(dia);
+  undo_set_transactionpoint(dia->undo);
+}
+
+void
+diagram_place_down_selected(Diagram *dia)
+{
+  GList *sorted_list;
+  GList *orig_list;
+  GList *tmp, *stmp;
+  GList *new_list = NULL;
+
+  if (dia->data->selected_count == 0)
+    return;
+
+  orig_list = g_list_copy(dia->data->active_layer->objects);
+  
+  sorted_list = diagram_get_sorted_selected(dia);
+  object_add_updates_list(orig_list, dia);
+
+  /* Sanity check */
+  g_assert(dia->data->selected_count == g_list_length(sorted_list));
+
+  new_list = g_list_copy(orig_list);
+  tmp = new_list;
+  stmp = sorted_list;
+
+  for (tmp = new_list; tmp != NULL; tmp = g_list_next(tmp)) {
+    if (stmp == NULL) break;
+    if (tmp->next == NULL) break;
+    if (tmp->data == stmp->data) {
+      /* This just takes care of any starting matches */
+      stmp = g_list_next(stmp);
+    } else if (tmp->next->data == stmp->data) {
+      /* This flips the non-selected element forwards, ala bubblesort */
+      void *swap = tmp->data;
+      tmp->data = tmp->next->data;
+      tmp->next->data = swap;
+      stmp = g_list_next(stmp);
+    }
+  }
+
+  layer_set_object_list(dia->data->active_layer, new_list);
+
+  undo_reorder_objects(dia, g_list_copy(sorted_list), orig_list);
+
+  diagram_modified(dia);
+  diagram_flush(dia);
+  undo_set_transactionpoint(dia->undo);
+}
+
+void
+diagram_set_filename(Diagram *dia, char *filename)
+{
+  GSList *l;
+  DDisplay *ddisp;
+  char *title;
+  
+  g_free(dia->filename);
+  dia->filename = g_strdup(filename);
+
+  title = diagram_get_name(dia);
+
+  l = dia->displays;
+  while (l!=NULL) {
+    ddisp = (DDisplay *) l->data;
+
+    ddisplay_set_title(ddisp, title);
+    
+    l = g_slist_next(l);
+  }
+
+  g_free(title);
+
+  layer_dialog_update_diagram_list();
+  recent_file_history_add((const char *)filename, NULL, 0);
+
+  diagram_tree_update_name(diagram_tree(), dia);
+}
+
+/** Returns a string with a 'sensible' (human-readable) name for the
+ * diagram.  The string should be freed after use.
+ * This name may or may not be the same as the filename.
+ */
+gchar *
+diagram_get_name(Diagram *dia)
+{
+  gchar *title = strrchr(dia->filename, G_DIR_SEPARATOR);
+  if (title==NULL) {
+    title = dia->filename;
+  } else {
+    title++;
+  }
+  
+  return g_strdup(title);
+}
+
+int diagram_modified_exists(void)
+{
+  GList *list;
+  Diagram *dia;
+
+  list = open_diagrams;
+
+  while (list != NULL) {
+    dia = (Diagram *) list->data;
+
+    if (dia->modified)
+      return TRUE;
+
+    list = g_list_next(list);
+  }
+  return FALSE;
+}
+
+void diagram_object_modified(Diagram *dia, Object *object)
+{
+  diagram_tree_update_object(diagram_tree(), dia, object);
+}
diff -Nuar cvs-dia/app/grid.c dia/app/grid.c
--- cvs-dia/app/grid.c	2003-08-21 22:59:37.000000000 +0200
+++ dia/app/grid.c	2003-08-30 19:39:49.000000000 +0200
@@ -50,7 +50,7 @@
   guint major_lines = ddisp->diagram->data->grid.major_lines;
   DiaRenderer *renderer = ddisp->renderer;
   DiaInteractiveRendererInterface *irenderer;
-  int major_count;
+  int major_count = 0;
 
   irenderer = DIA_GET_INTERACTIVE_RENDERER_INTERFACE (renderer);
 
@@ -87,7 +87,7 @@
   guint major_lines = ddisp->diagram->data->grid.major_lines;
   DiaRenderer *renderer = ddisp->renderer;
   DiaInteractiveRendererInterface *irenderer;
-  int major_count;
+  int major_count = 0;
 
   irenderer = DIA_GET_INTERACTIVE_RENDERER_INTERFACE (renderer);
 
@@ -114,6 +114,100 @@
   }
 }
 
+static void
+grid_draw_hex(DDisplay *ddisp, Rectangle *update, real length)
+{
+  real horiz_pos, vert_pos;
+  int to_x, to_y, x, y;
+  DiaRenderer *renderer = ddisp->renderer;
+  DiaInteractiveRendererInterface *irenderer;
+
+  irenderer = DIA_GET_INTERACTIVE_RENDERER_INTERFACE (renderer);
+
+  /* First horizontal lines: */
+  vert_pos = ceil( update->top / (length * sqrt(3)) ) * length * sqrt(3);
+  while (vert_pos <= update->bottom) {
+    horiz_pos = ceil( (update->left) / (3 * length) ) * length * 3 - length * 2.5;
+    while (horiz_pos <= update->right) {
+      ddisplay_transform_coords(ddisp, horiz_pos, vert_pos, &x, &y);
+      ddisplay_transform_coords(ddisp, horiz_pos + length, vert_pos, &to_x, &y);
+	  
+      irenderer->draw_pixel_line(renderer,
+				 x, y, to_x, y,
+				 &ddisp->diagram->data->grid.colour);
+      horiz_pos += 3 * length;
+    }
+	
+    vert_pos += sqrt(3) * length;
+  }
+
+  /*  Second horizontal lines: */
+  vert_pos = ceil( update->top / (length * sqrt(3)) ) * length * sqrt(3) - 0.5 * sqrt(3) * length;
+  while (vert_pos <= update->bottom) {
+    horiz_pos = ceil( (update->left) / (3 * length) ) * length * 3 - length;
+    while (horiz_pos <= update->right) {
+      ddisplay_transform_coords(ddisp, horiz_pos, vert_pos, &x, &y);
+      ddisplay_transform_coords(ddisp, horiz_pos+length, vert_pos, &to_x, &y);
+	  
+      irenderer->draw_pixel_line(renderer,
+				 x, y, to_x, y,
+				 &ddisp->diagram->data->grid.colour);
+      horiz_pos += 3 * length;
+    }
+	
+    vert_pos += sqrt(3) * length;
+  }
+
+  /* First \'s and /'s */
+  vert_pos = ceil( update->top / (length * sqrt(3)) ) * length * sqrt(3) - length * sqrt(3);
+  while (vert_pos <= update->bottom) {
+    horiz_pos = ceil( (update->left) / (3 * length) ) * length * 3 - length * 2.5;
+    while (horiz_pos <= update->right) {
+      ddisplay_transform_coords(ddisp, horiz_pos + length, vert_pos, &x, &y);
+      ddisplay_transform_coords(ddisp, horiz_pos + 1.5 * length, vert_pos + length * sqrt(3) * 0.5, &to_x, &to_y);
+	  
+      irenderer->draw_pixel_line(renderer,
+				 x, y, to_x, to_y,
+				 &ddisp->diagram->data->grid.colour);
+
+      ddisplay_transform_coords(ddisp, horiz_pos, vert_pos, &x, &y);
+      ddisplay_transform_coords(ddisp, horiz_pos - 0.5 * length, vert_pos + length * sqrt(3) * 0.5, &to_x, &to_y);
+	  
+      irenderer->draw_pixel_line(renderer,
+				 x, y, to_x, to_y,
+				 &ddisp->diagram->data->grid.colour);
+      horiz_pos += 3 * length;
+    }
+	
+    vert_pos += sqrt(3) * length;
+  }
+
+  /*  Second \'s and /'s */
+  vert_pos = ceil( update->top / (length * sqrt(3)) ) * length * sqrt(3) - 0.5 * sqrt(3) * length;
+  while (vert_pos <= update->bottom) {
+    horiz_pos = ceil( (update->left) / (3 * length) ) * length * 3 - length;
+    while (horiz_pos <= update->right) {
+      ddisplay_transform_coords(ddisp, horiz_pos, vert_pos, &x, &y);
+      ddisplay_transform_coords(ddisp, horiz_pos - 0.5 * length, vert_pos + 0.5 * sqrt(3) * length, &to_x, &to_y);
+	  
+      irenderer->draw_pixel_line(renderer,
+				 x, y, to_x, to_y,
+				 &ddisp->diagram->data->grid.colour);
+
+      ddisplay_transform_coords(ddisp, horiz_pos + length, vert_pos, &x, &y);
+      ddisplay_transform_coords(ddisp, horiz_pos + 1.5 * length, vert_pos + 0.5 * sqrt(3) * length, &to_x, &to_y);
+	  
+      irenderer->draw_pixel_line(renderer,
+				 x, y, to_x, to_y,
+				 &ddisp->diagram->data->grid.colour);
+      horiz_pos += 3 * length;
+    }
+	
+    vert_pos += sqrt(3) * length;
+  }
+
+}
+
 void
 grid_draw(DDisplay *ddisp, Rectangle *update)
 {
@@ -127,6 +221,7 @@
     /* distance between visible grid lines */
     real width_x = ddisp->diagram->data->grid.width_x;
     real width_y = ddisp->diagram->data->grid.width_y;
+    real width_w = ddisp->diagram->data->grid.width_w;
     if (ddisp->diagram->data->grid.dynamic) {
       width_x = width_y = calculate_dynamic_grid(ddisp, &width_x, &width_y);
     } else {
@@ -140,12 +235,16 @@
     DIA_RENDERER_GET_CLASS(renderer)->set_dashlength(renderer,
 						     ddisplay_untransform_length(ddisp, 31));
     
-    if (ddisplay_transform_length(ddisp, width_y) >= 2.0 &&
-	ddisplay_transform_length(ddisp, width_x) >= 2.0) {
-      /* Vertical lines: */
-      grid_draw_vertical_lines(ddisp, update, width_x);
-      /* Horizontal lines: */
-      grid_draw_horizontal_lines(ddisp, update, width_y);
+    if (prefs.grid.hex) {
+      grid_draw_hex(ddisp, update, width_w);
+    } else {
+      if (ddisplay_transform_length(ddisp, width_y) >= 2.0 &&
+	  ddisplay_transform_length(ddisp, width_x) >= 2.0) {
+	/* Vertical lines: */
+	grid_draw_vertical_lines(ddisp, update, width_x);
+	/* Horizontal lines: */
+	grid_draw_horizontal_lines(ddisp, update, width_y);
+      }
     }
   }
 }
@@ -205,12 +304,37 @@
 snap_to_grid(DDisplay *ddisp, coord *x, coord *y)
 {
   if (ddisp->grid.snap) {
-    real width_x = ddisp->diagram->data->grid.width_x;
-    real width_y = ddisp->diagram->data->grid.width_y;
-    if (prefs.grid.dynamic) {
-      calculate_dynamic_grid(ddisp, &width_x, &width_y);
+    if (prefs.grid.hex) {
+      real width_x = ddisp->diagram->data->grid.width_w;
+      real x_mod = (*x - 1*width_x) - floor((*x - 1*width_x) / (3*width_x)) * 3 * width_x;
+      real y_mod = (*y - 0.25*sqrt(3) * width_x) -
+	floor((*y - 0.25 * sqrt(3) * width_x) / (sqrt(3)*width_x)) * sqrt(3) * width_x;
+
+      if ( x_mod < (1.5 * width_x) ) {
+	if ( y_mod < 0.5 * sqrt(3) * width_x ) {
+	  *x = floor((*x + 0.5*width_x) / (3*width_x)) * 3 * width_x + 2 * width_x;
+	  *y = floor((*y - 0.25 * sqrt(3) * width_x) / (sqrt(3)*width_x)) * sqrt(3) * width_x + 0.5 * sqrt(3) * width_x;
+	} else {
+	  *x = floor((*x + 0.5*width_x) / (3*width_x)) * 3 * width_x + 1.5 * width_x;
+	  *y = floor((*y - 0.25 * sqrt(3) * width_x) / (sqrt(3)*width_x)) * sqrt(3) * width_x + sqrt(3) * width_x;
+	}
+      } else {
+	if ( y_mod < 0.5 * sqrt(3) * width_x ) {
+	  *x = floor((*x + 0.5*width_x) / (3*width_x)) * 3 * width_x ;
+	  *y = floor((*y - 0.25 * sqrt(3) * width_x) / (sqrt(3)*width_x)) * sqrt(3) * width_x + 0.5 * sqrt(3) * width_x;
+	} else {
+	  *x = floor((*x + 0.5*width_x) / (3*width_x)) * 3 * width_x + 0.5 * width_x;
+	  *y = floor((*y - 0.25 * sqrt(3) * width_x) / (sqrt(3)*width_x)) * sqrt(3) * width_x + sqrt(3) * width_x;
+	}
+      }
+    } else {
+      real width_x = ddisp->diagram->data->grid.width_x;
+      real width_y = ddisp->diagram->data->grid.width_y;
+      if (prefs.grid.dynamic) {
+	calculate_dynamic_grid(ddisp, &width_x, &width_y);
+      }
+      *x = ROUND((*x) / width_x) * width_x;
+      *y = ROUND((*y) / width_y) * width_y;
     }
-    *x = ROUND((*x) / width_x) * width_x;
-    *y = ROUND((*y) / width_y) * width_y;
   }
 }
diff -Nuar cvs-dia/app/grid.c.orig dia/app/grid.c.orig
--- cvs-dia/app/grid.c.orig	1970-01-01 01:00:00.000000000 +0100
+++ dia/app/grid.c.orig	2003-08-30 19:39:04.000000000 +0200
@@ -0,0 +1,216 @@
+/* Dia -- an diagram creation/manipulation program
+ * Copyright (C) 1998 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
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <glib.h>
+
+#include "intl.h"
+#include "grid.h"
+#include "preferences.h"
+
+/** Calculate the width (in cm) of the gap between grid lines in dynamic
+ * grid mode.
+ */
+static real
+calculate_dynamic_grid(DDisplay *ddisp, real *width_x, real *width_y)
+{
+  real zoom = ddisplay_untransform_length(ddisp, 1.0);
+  /* Twiddle zoom to make change-over appropriate */
+  zoom *= 5;
+  return pow(10, ceil(log10(zoom)));
+}
+
+static void
+grid_draw_horizontal_lines(DDisplay *ddisp, Rectangle *update, real length) 
+{
+  int x, y;
+  real pos;
+  int height, width;
+  guint major_lines = ddisp->diagram->data->grid.major_lines;
+  DiaRenderer *renderer = ddisp->renderer;
+  DiaInteractiveRendererInterface *irenderer;
+  int major_count;
+
+  irenderer = DIA_GET_INTERACTIVE_RENDERER_INTERFACE (renderer);
+
+  pos = ceil( update->top / length ) * length;
+  ddisplay_transform_coords(ddisp, update->left, pos, &x, &y);
+  ddisplay_transform_coords(ddisp, update->right, update->bottom, &width, &height);
+
+  if (major_lines) {
+    major_count = pos/length;
+    major_count %= major_lines;
+  }
+
+  while (y < height) {
+    if (major_lines) {
+      if (major_count == 0)
+	DIA_RENDERER_GET_CLASS(renderer)->set_linestyle(renderer, LINESTYLE_SOLID);
+      else
+	DIA_RENDERER_GET_CLASS(renderer)->set_linestyle(renderer, LINESTYLE_DOTTED);
+      major_count = (major_count+1)%major_lines;
+    }
+    irenderer->draw_pixel_line(renderer, x, y, width, y,
+			       &ddisp->diagram->data->grid.colour);
+    pos += length;
+    ddisplay_transform_coords(ddisp, update->left, pos, &x, &y);
+  }
+}
+
+static void
+grid_draw_vertical_lines(DDisplay *ddisp, Rectangle *update, real length) 
+{
+  int x = 0, y = 0;
+  real pos;
+  int height, width;
+  guint major_lines = ddisp->diagram->data->grid.major_lines;
+  DiaRenderer *renderer = ddisp->renderer;
+  DiaInteractiveRendererInterface *irenderer;
+  int major_count;
+
+  irenderer = DIA_GET_INTERACTIVE_RENDERER_INTERFACE (renderer);
+
+  pos = ceil( update->left / length ) * length;
+  ddisplay_transform_coords(ddisp, update->right, update->bottom, &width, &height);
+
+  if (major_lines) {
+    major_count = pos/length;
+    major_count %= major_lines;
+  }
+
+  while (x < width) {
+    ddisplay_transform_coords(ddisp, pos, update->top, &x, &y);
+    if (major_lines) {
+      if (major_count == 0)
+	DIA_RENDERER_GET_CLASS(renderer)->set_linestyle(renderer, LINESTYLE_SOLID);
+      else
+	DIA_RENDERER_GET_CLASS(renderer)->set_linestyle(renderer, LINESTYLE_DOTTED);
+      major_count = (major_count+1)%major_lines;
+    }
+    irenderer->draw_pixel_line(renderer, x, y, x, height,
+			       &ddisp->diagram->data->grid.colour);
+    pos += length;
+  }
+}
+
+void
+grid_draw(DDisplay *ddisp, Rectangle *update)
+{
+  Grid *grid = &ddisp->grid;
+  DiaRenderer *renderer = ddisp->renderer;
+  int major_lines;
+
+  if (grid->visible) {
+    int width = dia_renderer_get_width_pixels(ddisp->renderer);
+    int height = dia_renderer_get_height_pixels(ddisp->renderer);
+    /* distance between visible grid lines */
+    real width_x = ddisp->diagram->data->grid.width_x;
+    real width_y = ddisp->diagram->data->grid.width_y;
+    if (ddisp->diagram->data->grid.dynamic) {
+      width_x = width_y = calculate_dynamic_grid(ddisp, &width_x, &width_y);
+    } else {
+      width_x = ddisp->diagram->data->grid.width_x *
+	ddisp->diagram->data->grid.visible_x;
+      width_y = ddisp->diagram->data->grid.width_y *
+	ddisp->diagram->data->grid.visible_y;
+    }
+
+    DIA_RENDERER_GET_CLASS(renderer)->set_linewidth(renderer, 0.0);
+    DIA_RENDERER_GET_CLASS(renderer)->set_dashlength(renderer,
+						     ddisplay_untransform_length(ddisp, 31));
+    
+    if (ddisplay_transform_length(ddisp, width_y) >= 2.0 &&
+	ddisplay_transform_length(ddisp, width_x) >= 2.0) {
+      /* Vertical lines: */
+      grid_draw_vertical_lines(ddisp, update, width_x);
+      /* Horizontal lines: */
+      grid_draw_horizontal_lines(ddisp, update, width_y);
+    }
+  }
+}
+
+void
+pagebreak_draw(DDisplay *ddisp, Rectangle *update)
+{
+  DiaRenderer *renderer = ddisp->renderer;
+  DiaInteractiveRendererInterface *irenderer;
+
+  int width = dia_renderer_get_width_pixels(ddisp->renderer);
+  int height = dia_renderer_get_height_pixels(ddisp->renderer);
+  
+  irenderer = DIA_GET_INTERACTIVE_RENDERER_INTERFACE (renderer);
+  if (prefs.pagebreak.visible) {
+    Diagram *dia = ddisp->diagram;
+    real origx = 0, origy = 0, pos;
+    real pwidth = dia->data->paper.width;
+    real pheight = dia->data->paper.height;
+    int x,y;
+
+    DIA_RENDERER_GET_CLASS(renderer)->set_linewidth(renderer, 0.0);
+    DIA_RENDERER_GET_CLASS(renderer)->set_dashlength(renderer,
+				    ddisplay_untransform_length(ddisp, 31));
+    if (prefs.pagebreak.solid)
+      DIA_RENDERER_GET_CLASS(renderer)->set_linestyle(renderer, LINESTYLE_SOLID);
+    else
+      DIA_RENDERER_GET_CLASS(renderer)->set_linestyle(renderer, LINESTYLE_DOTTED);
+
+    if (dia->data->paper.fitto) {
+      origx = dia->data->extents.left;
+      origy = dia->data->extents.top;
+    }
+
+    /* vertical lines ... */
+    pos = origx + ceil((update->left - origx) / pwidth) * pwidth;
+    while (pos <= update->right) {
+      ddisplay_transform_coords(ddisp, pos,0,&x,&y);
+      irenderer->draw_pixel_line(renderer,
+                                 x, 0, x, height,
+				 &dia->data->pagebreak_color);
+      pos += pwidth;
+    }
+    /* Horizontal lines: */
+    pos = origy + ceil((update->top - origy) / pheight) * pheight;
+    while (pos <= update->bottom) {
+      ddisplay_transform_coords(ddisp, 0,pos,&x,&y);
+      irenderer->draw_pixel_line(renderer,
+				 0, y, width, y,
+				 &dia->data->pagebreak_color);
+      pos += pheight;
+    }
+  }
+}
+
+void
+snap_to_grid(DDisplay *ddisp, coord *x, coord *y)
+{
+  if (ddisp->grid.snap) {
+    real width_x = ddisp->diagram->data->grid.width_x;
+    real width_y = ddisp->diagram->data->grid.width_y;
+    if (prefs.grid.dynamic) {
+      calculate_dynamic_grid(ddisp, &width_x, &width_y);
+    }
+    *x = ROUND((*x) / width_x) * width_x;
+    *y = ROUND((*y) / width_y) * width_y;
+  }
+}
diff -Nuar cvs-dia/app/preferences.c dia/app/preferences.c
--- cvs-dia/app/preferences.c	2003-08-27 16:14:49.000000000 +0200
+++ dia/app/preferences.c	2003-08-30 19:39:49.000000000 +0200
@@ -157,6 +157,9 @@
   { "grid_y", PREF_UREAL, PREF_OFFSET(grid.y), &default_real_one, 3, N_("Y Size:") },
   { "grid_colour", PREF_COLOUR, PREF_OFFSET(new_diagram.grid_color), &default_colour, 3, N_("Colour:") },
   { "grid_major", PREF_UINT, PREF_OFFSET(grid.major_lines), &default_major_lines, 3, N_("Lines per major line") },
+  { "grid_hex", PREF_BOOLEAN, PREF_OFFSET(grid.hex), &default_false, 3, N_("Hex grid") },
+  { "grid_w", PREF_UREAL, PREF_OFFSET(grid.w), &default_real_one, 3, N_("Hex Size:")
+ },
   /*  { "grid_solid", PREF_BOOLEAN, PREF_OFFSET(grid.solid), &default_true, 3, N_("Solid lines:") },  */
 
   { "render_bounding_boxes", PREF_BOOLEAN,PREF_OFFSET(render_bounding_boxes),
diff -Nuar cvs-dia/app/preferences.c.orig dia/app/preferences.c.orig
--- cvs-dia/app/preferences.c.orig	1970-01-01 01:00:00.000000000 +0100
+++ dia/app/preferences.c.orig	2003-08-30 19:39:04.000000000 +0200
@@ -0,0 +1,848 @@
+/* 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.
+ */
+#include <config.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_STDDEF_H
+#include <stddef.h>
+#endif
+#include <locale.h>
+
+#include <gtk/gtk.h>
+
+#include "intl.h"
+#include "widgets.h"
+#include "diagram.h"
+#include "message.h"
+#include "preferences.h"
+#include "dia_dirs.h"
+#include "diagramdata.h"
+#include "paper.h"
+#include "interface.h"
+
+#ifdef G_OS_WIN32
+#include <io.h> /* open, close */
+#endif
+
+struct DiaPreferences prefs;
+
+enum DiaPrefType {
+  PREF_NONE,
+  PREF_BOOLEAN,
+  PREF_INT,
+  PREF_UINT,
+  PREF_REAL,
+  PREF_UREAL,
+  PREF_COLOUR,
+  PREF_CHOICE,
+  PREF_STRING,
+  PREF_END_GROUP
+};
+
+typedef struct _DiaPrefData {
+  char *name;
+  enum DiaPrefType type;
+  int offset;
+  void *default_value;
+  int tab;
+  char *label_text;
+  GtkWidget *widget;
+  gboolean hidden;
+  GList *(*choice_list_function)();
+} DiaPrefData;
+
+static int default_true = 1;
+static int default_false = 0;
+static int default_major_lines = 5;
+static real default_real_one = 1.0;
+static real default_real_zoom = 100.0;
+static int default_int_w = 500;
+static int default_int_h = 400;
+static int default_undo_depth = 15;
+static guint default_recent_documents = 5;
+static Color default_colour = DEFAULT_GRID_COLOR;
+static Color pbreak_colour = DEFAULT_PAGEBREAK_COLOR;
+static guint default_dtree_dia_sort = DIA_TREE_SORT_INSERT;
+static guint default_dtree_obj_sort = DIA_TREE_SORT_INSERT;
+static const gchar *default_paper_name = NULL;
+
+struct DiaPrefsTab {
+  char *title;
+  GtkTable *table;
+  int row;
+};
+
+struct DiaPrefsTab prefs_tabs[] =
+{
+  {N_("User Interface"), NULL, 0},
+  {N_("Diagram Defaults"), NULL, 0},
+  {N_("View Defaults"), NULL, 0},
+  {N_("Grid Lines"), NULL, 0},
+  {N_("Diagram Tree"), NULL, 0},
+};
+
+#define NUM_PREFS_TABS (sizeof(prefs_tabs)/sizeof(struct DiaPrefsTab))
+
+/* retrive a structure offset */
+#ifdef offsetof
+#define PREF_OFFSET(field)        ((int) offsetof (struct DiaPreferences, field))
+#else /* !offsetof */
+#define PREF_OFFSET(field)        ((int) ((char*) &((struct DiaPreferences *) 0)->field))
+#endif /* !offsetof */
+
+DiaPrefData prefs_data[] =
+{
+  { "reset_tools_after_create", PREF_BOOLEAN, PREF_OFFSET(reset_tools_after_create), &default_true, 0, N_("Reset tools after create") },
+  { "compress_save", PREF_BOOLEAN, PREF_OFFSET(new_diagram.compress_save), &default_true, 0, N_("Compress saved files") },
+  { "undo_depth", PREF_UINT, PREF_OFFSET(undo_depth), &default_undo_depth, 0, N_("Number of undo levels:") },
+  { "reverse_rubberbanding_intersects", PREF_BOOLEAN, PREF_OFFSET(reverse_rubberbanding_intersects), &default_true, 0, N_("Reverse dragging selects\nintersecting objects") },
+  { "recent_documents_list_size", PREF_UINT, PREF_OFFSET(recent_documents_list_size), &default_recent_documents, 0, N_("Recent documents list size:") },
+  { "use_menu_bar", PREF_BOOLEAN, PREF_OFFSET(new_view.use_menu_bar), &default_false, 0, N_("Use menu bar") },
+  { "toolbox_on_top", PREF_BOOLEAN, PREF_OFFSET(toolbox_on_top),
+    &default_false, 0, N_("Keep tool box on top of diagram windows") },
+  
+  { NULL, PREF_NONE, 0, NULL, 1, N_("New diagram:") },
+  { "is_portrait", PREF_BOOLEAN, PREF_OFFSET(new_diagram.is_portrait), &default_true, 1, N_("Portrait") },
+  { "new_diagram_papertype", PREF_CHOICE, PREF_OFFSET(new_diagram.papertype),
+    &default_paper_name, 1, N_("Paper type:"), NULL, FALSE,
+    get_paper_name_list },
+  { "new_diagram_bgcolour", PREF_COLOUR, PREF_OFFSET(new_diagram.bg_color),
+    &color_white, 1, N_("Background Colour:") },
+  { NULL, PREF_END_GROUP, 0, NULL, 1, NULL },
+
+  { NULL, PREF_NONE, 0, NULL, 1, N_("New window:") },
+  { "new_view_width", PREF_UINT, PREF_OFFSET(new_view.width), &default_int_w, 1, N_("Width:") },
+  { "new_view_height", PREF_UINT, PREF_OFFSET(new_view.height), &default_int_h, 1, N_("Height:") },
+  { "new_view_zoom", PREF_UREAL, PREF_OFFSET(new_view.zoom), &default_real_zoom, 1, N_("Magnify:") },
+  { NULL, PREF_END_GROUP, 0, NULL, 1, NULL },
+
+  { NULL, PREF_NONE, 0, NULL, 1, N_("Connection Points:") },
+  { "show_cx_pts", PREF_BOOLEAN, PREF_OFFSET(show_cx_pts), &default_true, 1, N_("Visible") },
+  { NULL, PREF_END_GROUP, 0, NULL, 1, NULL },
+
+  { NULL, PREF_NONE, 0, NULL, 2, N_("Page breaks:") },
+  { "pagebreak_visible", PREF_BOOLEAN, PREF_OFFSET(pagebreak.visible), &default_true, 2, N_("Visible") },
+  { "pagebreak_colour", PREF_COLOUR, PREF_OFFSET(new_diagram.pagebreak_color), &pbreak_colour, 2, N_("Colour:") },
+  { "pagebreak_solid", PREF_BOOLEAN, PREF_OFFSET(pagebreak.solid), &default_true, 2, N_("Solid lines") },
+  { NULL, PREF_END_GROUP, 0, NULL, 2, NULL },
+  
+  /*{ NULL, PREF_NONE, 0, NULL, 3, N_("Grid:") }, */
+  { "grid_visible", PREF_BOOLEAN, PREF_OFFSET(grid.visible), &default_true, 3, N_("Visible") },
+  { "grid_snap", PREF_BOOLEAN, PREF_OFFSET(grid.snap), &default_false, 3, N_("Snap to") },
+  { "grid_dynamic", PREF_BOOLEAN, PREF_OFFSET(grid.dynamic), &default_true, 3, N_("Dynamic grid resizing") },
+  { "grid_x", PREF_UREAL, PREF_OFFSET(grid.x), &default_real_one, 3, N_("X Size:") },
+  { "grid_y", PREF_UREAL, PREF_OFFSET(grid.y), &default_real_one, 3, N_("Y Size:") },
+  { "grid_colour", PREF_COLOUR, PREF_OFFSET(new_diagram.grid_color), &default_colour, 3, N_("Colour:") },
+  { "grid_major", PREF_UINT, PREF_OFFSET(grid.major_lines), &default_major_lines, 3, N_("Lines per major line") },
+  /*  { "grid_solid", PREF_BOOLEAN, PREF_OFFSET(grid.solid), &default_true, 3, N_("Solid lines:") },  */
+
+  { "render_bounding_boxes", PREF_BOOLEAN,PREF_OFFSET(render_bounding_boxes),
+    &default_false,0,"render bounding boxes",NULL, TRUE},
+
+  /* There's really no reason to not pertty format it, and allowing non-pretty
+     can lead to problems with long lines, CVS etc. 
+  { "pretty_formated_xml", PREF_BOOLEAN,PREF_OFFSET(pretty_formated_xml),
+    &default_true,0,"pretty formated xml",NULL, TRUE},
+  */
+
+  { "prefer_psprint", PREF_BOOLEAN,PREF_OFFSET(prefer_psprint),
+    &default_false,0,"prefer psprint", NULL, TRUE},
+
+  { "recent_sheet", PREF_UINT,PREF_OFFSET(recent_sheet),
+    &default_false,0,"recent selected sheet:",NULL, TRUE},
+
+  { NULL, PREF_NONE, 0, NULL, 4, N_("Diagram tree window:") },
+  { "diagram_tree_save_hidden", PREF_BOOLEAN, PREF_OFFSET(dia_tree.save_hidden),
+    &default_false, 4, N_("Save hidden object types")},
+  { "diagram_tree_dia_sort", PREF_UINT, PREF_OFFSET(dia_tree.dia_sort),
+    &default_dtree_dia_sort, 4, "default diagram sort order", NULL, TRUE},
+  { "diagram_tree_obj_sort", PREF_UINT, PREF_OFFSET(dia_tree.obj_sort),
+    &default_dtree_obj_sort, 4, "default object sort order", NULL, TRUE},
+  { "diagram_tree_hidden", PREF_STRING, PREF_OFFSET(dia_tree.hidden),
+    &DIA_TREE_DEFAULT_HIDDEN, 4, "hidden type list", NULL, TRUE},
+  { NULL, PREF_END_GROUP, 0, NULL, 4, NULL },
+};
+
+#define NUM_PREFS_DATA (sizeof(prefs_data)/sizeof(DiaPrefData))
+
+static const GScannerConfig     dia_prefs_scanner_config =
+{
+  (
+   " \t\n"
+   )                    /* cset_skip_characters */,
+  (
+   G_CSET_a_2_z
+   "_"
+   G_CSET_A_2_Z
+   )                    /* cset_identifier_first */,
+  (
+   G_CSET_a_2_z
+   "_-0123456789"
+   G_CSET_A_2_Z
+   )                    /* cset_identifier_nth */,
+  ( "#\n" )             /* cpair_comment_single */,
+  
+  TRUE                  /* case_sensitive */,
+  
+  FALSE                 /* skip_comment_multi */,
+  TRUE                  /* skip_comment_single */,
+  FALSE                 /* scan_comment_multi */,
+  TRUE                  /* scan_identifier */,
+  TRUE                  /* scan_identifier_1char */,
+  FALSE                 /* scan_identifier_NULL */,
+  TRUE                  /* scan_symbols */,
+  FALSE                 /* scan_binary */,
+  FALSE                 /* scan_octal */,
+  TRUE                  /* scan_float */,
+  TRUE                  /* scan_hex */,
+  FALSE                 /* scan_hex_dollar */,
+  FALSE                 /* scan_string_sq */,
+  TRUE                  /* scan_string_dq */,
+  TRUE                  /* numbers_2_int */,
+  FALSE                 /* int_2_float */,
+  FALSE                 /* identifier_2_string */,
+  TRUE                  /* char_2_token */,
+  FALSE                 /* symbol_2_token */,
+  FALSE                 /* scope_0_fallback */,
+};
+
+typedef enum {
+  DIA_PREFS_TOKEN_BOOLEAN = G_TOKEN_LAST
+} DiaPrefsTokenType;
+
+static void prefs_create_dialog(void);
+static void prefs_set_value_in_widget(GtkWidget * widget, DiaPrefData *data,  char *ptr);
+static void prefs_get_value_from_widget(GtkWidget * widget, DiaPrefData *data, char *ptr);
+static void prefs_update_dialog_from_prefs(void);
+static void prefs_update_prefs_from_dialog(void);
+static gint prefs_apply(GtkWidget *widget, gpointer data);
+
+
+static GtkWidget *prefs_dialog = NULL;
+
+void
+prefs_show(void)
+{
+  prefs_create_dialog();
+  gtk_widget_show(prefs_dialog);
+  
+  prefs_update_dialog_from_prefs();
+}
+
+void
+prefs_set_defaults(void)
+{
+  int i;
+  char *ptr;
+
+  /* Since we can't call this in static initialization, we have to
+   * do it here.
+   */
+  if (default_paper_name == NULL)
+    default_paper_name = get_paper_name(get_default_paper());
+
+  for (i=0;i<NUM_PREFS_DATA;i++) {
+    ptr = (char *)&prefs + prefs_data[i].offset;
+
+    switch (prefs_data[i].type) {
+    case PREF_BOOLEAN:
+    case PREF_INT:
+    case PREF_UINT:
+      *(int *)ptr = *(int *)prefs_data[i].default_value;
+      break;
+    case PREF_REAL:
+    case PREF_UREAL:
+      *(real *)ptr = *(real *)prefs_data[i].default_value;
+      break;
+    case PREF_COLOUR:
+      *(Color *)ptr = *(Color *)prefs_data[i].default_value;
+      break;
+    case PREF_CHOICE:
+    case PREF_STRING:
+      *(gchar **)ptr = *(gchar **)prefs_data[i].default_value;
+      break;
+    case PREF_NONE:
+    case PREF_END_GROUP:
+      break;
+    }
+  }
+}
+
+void
+prefs_save(void)
+{
+  int i;
+  char *ptr;
+  gchar *filename;
+  char *old_locale;
+  FILE *file;
+
+  filename = dia_config_filename("diarc");
+
+  file = fopen(filename, "w");
+
+  if (!file) {
+    message_error(_("Could not open `%s' for writing"), filename);
+    g_free(filename);
+    return;
+  }
+  
+  g_free(filename);
+
+  old_locale = setlocale(LC_NUMERIC, "C");
+  fprintf(file, "# Note: This file is automatically generated by Dia\n");
+  for (i=0;i<NUM_PREFS_DATA;i++) {
+    if ((prefs_data[i].type == PREF_NONE) || (prefs_data[i].type == PREF_END_GROUP))
+      continue;
+    
+    fprintf(file, "%s=", prefs_data[i].name);
+    
+    ptr = (char *)&prefs + prefs_data[i].offset;
+
+    switch (prefs_data[i].type) {
+    case PREF_BOOLEAN:
+      fprintf(file, (*(int *)ptr)?"true\n":"false\n");
+      break;
+    case PREF_INT:
+    case PREF_UINT:
+      fprintf(file, "%d\n", *(int *)ptr);
+      break;
+    case PREF_REAL:
+    case PREF_UREAL:
+      
+      fprintf(file, "%f\n", (double) *(real *)ptr);
+      break;
+    case PREF_COLOUR:
+      fprintf(file, "%f %f %f\n", (double) ((Color *)ptr)->red,
+	      (double) ((Color *)ptr)->green, (double) ((Color *)ptr)->blue);
+      break;
+    case PREF_CHOICE:
+    case PREF_STRING:
+      fprintf(file, "\"%s\"\n", *(gchar **)ptr);
+      break;
+    case PREF_NONE:
+    case PREF_END_GROUP:
+      break;
+    }
+  }
+  setlocale(LC_NUMERIC, old_locale);
+  fclose(file);
+}
+
+
+static guint
+prefs_parse_line(GScanner *scanner)
+{
+  guint token;
+  int symbol_nr;
+  char *ptr;
+  
+  token = g_scanner_get_next_token(scanner);
+  if (token != G_TOKEN_SYMBOL)
+    return G_TOKEN_SYMBOL;
+
+  symbol_nr = GPOINTER_TO_INT(scanner->value.v_symbol);
+  
+  token = g_scanner_get_next_token(scanner);
+  if (token != G_TOKEN_EQUAL_SIGN)
+    return G_TOKEN_EQUAL_SIGN;
+
+  token = g_scanner_get_next_token(scanner);
+
+  ptr = (unsigned char *)&prefs + prefs_data[symbol_nr].offset;
+  
+  switch (prefs_data[symbol_nr].type) {
+  case PREF_BOOLEAN:
+    if (token != G_TOKEN_IDENTIFIER)
+      return G_TOKEN_IDENTIFIER;
+    
+    if (strcmp(scanner->value.v_string, "true")==0)
+      *(int *)ptr = 1;
+    else
+    *(int *)ptr = 0;
+    break;
+    
+  case PREF_INT:
+  case PREF_UINT:
+    if (token != G_TOKEN_INT)
+      return G_TOKEN_INT;
+    
+    *(int *)ptr = scanner->value.v_int;
+    break;
+
+  case PREF_REAL:
+  case PREF_UREAL:
+    if (token != G_TOKEN_FLOAT)
+      return G_TOKEN_FLOAT;
+    
+    *(real *)ptr = scanner->value.v_float;
+    break;
+  case PREF_COLOUR:
+    if (token != G_TOKEN_FLOAT)
+      return G_TOKEN_FLOAT;
+    ((Color *)ptr)->red = scanner->value.v_float;
+
+    token = g_scanner_get_next_token(scanner);
+    if (token != G_TOKEN_FLOAT)
+      return G_TOKEN_FLOAT;
+    ((Color *)ptr)->green = scanner->value.v_float;
+
+    token = g_scanner_get_next_token(scanner);
+    if (token != G_TOKEN_FLOAT)
+      return G_TOKEN_FLOAT;
+    ((Color *)ptr)->blue = scanner->value.v_float;
+
+    break;
+  case PREF_CHOICE:
+  case PREF_STRING:
+    if (token != G_TOKEN_STRING)
+      return G_TOKEN_STRING;
+
+    *(char **)ptr = g_strdup(scanner->value.v_string);
+    break;
+  case PREF_NONE:
+  case PREF_END_GROUP:
+    break;
+  }
+
+  return G_TOKEN_NONE;
+}
+
+
+void
+prefs_load(void)
+{
+  int i;
+  gchar *filename;
+  int fd;
+  GScanner *scanner;
+  guint expected_token;
+
+  filename = dia_config_filename("diarc");
+
+  fd = open(filename, O_RDONLY);
+
+  if (fd < 0) {
+    const gchar *homedir = g_get_home_dir();
+
+    g_free(filename);
+    filename = g_strconcat(homedir, G_DIR_SEPARATOR_S ".diarc", NULL);
+    fd = open(filename, O_RDONLY);
+  }
+  g_free(filename);
+
+  prefs_set_defaults();
+
+  if (fd < 0) {
+    return;
+  }
+
+  scanner = g_scanner_new ((GScannerConfig *) &dia_prefs_scanner_config);
+ 
+  g_scanner_input_file (scanner, fd);
+
+  scanner->input_name = filename;
+  for (i = 0; i < NUM_PREFS_DATA; i++)
+    if (prefs_data[i].name != NULL) {
+      g_scanner_add_symbol(scanner, prefs_data[i].name,
+			   GINT_TO_POINTER(i));
+    }
+  while (1) {
+    if (g_scanner_peek_next_token(scanner) == G_TOKEN_EOF) {
+      break;
+    } 
+
+    expected_token = prefs_parse_line(scanner);
+      
+    if (expected_token != G_TOKEN_NONE) {
+      gchar *symbol_name;
+      gchar *msg;
+      
+      msg = NULL;
+      symbol_name = NULL;
+      g_scanner_unexp_token (scanner,
+			     expected_token,
+			     NULL,
+			     "keyword",
+			     symbol_name,
+			     msg,
+			     TRUE);
+    }
+  }
+  
+  g_scanner_destroy (scanner);
+ 
+  close(fd);
+  render_bounding_boxes = prefs.render_bounding_boxes;
+}
+
+static void
+prefs_set_value_in_widget(GtkWidget * widget, DiaPrefData *data,
+			  char *ptr)
+{
+  switch(data->type) {
+  case PREF_BOOLEAN:
+    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), *((int *)ptr));
+    break;
+  case PREF_INT:
+  case PREF_UINT:
+    gtk_spin_button_set_value(GTK_SPIN_BUTTON(widget),
+			      (gfloat) (*((int *)ptr)));
+    break;
+  case PREF_REAL:
+  case PREF_UREAL: 
+    gtk_spin_button_set_value(GTK_SPIN_BUTTON(widget),
+			      (gfloat) (*((real *)ptr)));
+    break;
+  case PREF_COLOUR:
+    dia_color_selector_set_color(DIACOLORSELECTOR(widget), (Color *)ptr);
+    break;
+  case PREF_CHOICE: {
+    GList *names = (data->choice_list_function)();
+    int index;
+    for (index = 0; names != NULL; names = g_list_next(names), index++) {
+      if (!strcmp(*((gchar**)ptr), (gchar *)names->data))
+	break;
+    }
+    if (names == NULL) return;
+    gtk_option_menu_set_history(GTK_OPTION_MENU(widget), index);
+    gtk_menu_set_active(GTK_MENU(gtk_option_menu_get_menu(GTK_OPTION_MENU(widget))), index);
+    gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gtk_menu_get_active(GTK_MENU(gtk_option_menu_get_menu(GTK_OPTION_MENU(widget))))), TRUE);
+    break;
+  }
+  case PREF_STRING:
+    gtk_entry_set_text(GTK_ENTRY(widget), (gchar *)(*((gchar **)ptr)));
+    break;
+  case PREF_NONE:
+  case PREF_END_GROUP:
+    break;
+  }
+}
+
+static void
+prefs_get_value_from_widget(GtkWidget * widget, DiaPrefData *data,
+			    char *ptr)
+{
+  switch(data->type) {
+  case PREF_BOOLEAN:
+    *((int *)ptr) = GTK_TOGGLE_BUTTON(widget)->active;    
+    break;
+  case PREF_INT:
+  case PREF_UINT:
+    *((int *)ptr) =
+      gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
+    break;
+  case PREF_REAL:
+  case PREF_UREAL:
+    *((real *)ptr) = (real)
+      gtk_spin_button_get_value_as_float(GTK_SPIN_BUTTON(widget));
+    break;
+  case PREF_COLOUR:
+    dia_color_selector_get_color(DIACOLORSELECTOR(widget), (Color *)ptr);
+    break;
+  case PREF_CHOICE: {
+    int index = gtk_option_menu_get_history(GTK_OPTION_MENU(widget));
+    GList *names = (data->choice_list_function)();
+    *((gchar **)ptr) = g_strdup((gchar *)g_list_nth_data(names, index));
+    break;
+  }
+  case PREF_STRING:
+    *((gchar **)ptr) = (gchar *)
+      gtk_entry_get_text(GTK_ENTRY(widget));
+    break;
+  case PREF_NONE:
+  case PREF_END_GROUP:
+    break;
+  }
+}
+
+static void
+prefs_boolean_toggle(GtkWidget *widget, gpointer data)
+{
+  guint active = GTK_TOGGLE_BUTTON(widget)->active;
+  gtk_button_set_label(GTK_BUTTON(widget), active ? _("Yes") : _("No"));
+}
+
+static GtkWidget *
+prefs_get_property_widget(DiaPrefData *data)
+{
+  GtkWidget *widget = NULL;
+  GtkAdjustment *adj;
+  
+  switch(data->type) {
+  case PREF_BOOLEAN:
+    widget = gtk_toggle_button_new_with_label (_("No"));
+    gtk_signal_connect (GTK_OBJECT (widget), "toggled",
+			GTK_SIGNAL_FUNC (prefs_boolean_toggle), NULL);
+    break;
+  case PREF_INT:
+    adj = GTK_ADJUSTMENT(gtk_adjustment_new(0.0,
+					    G_MININT, G_MAXINT,
+					    1.0, 10.0, 10.0 ));
+    widget = gtk_spin_button_new (adj, 1.0, 0);
+    gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(widget), TRUE);
+    gtk_widget_set_usize(widget, 80, -1);
+    break;
+  case PREF_UINT:
+    adj = GTK_ADJUSTMENT(gtk_adjustment_new(0.0,
+					    0.0, G_MAXINT,
+					    1.0, 10.0, 10.0 ));
+    widget = gtk_spin_button_new (adj, 1.0, 0);
+    gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(widget), TRUE);
+    gtk_widget_set_usize(widget, 80, -1);
+    break;
+  case PREF_REAL:
+    adj = GTK_ADJUSTMENT(gtk_adjustment_new(0.0,
+					    G_MINFLOAT, G_MAXFLOAT,
+					    1.0, 10.0, 10.0 ));
+    widget = gtk_spin_button_new (adj, 1.0, 3);
+    gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(widget), TRUE);
+    gtk_widget_set_usize(widget, 80, -1);
+    break;
+  case PREF_UREAL:
+    adj = GTK_ADJUSTMENT(gtk_adjustment_new(0.0,
+					    0.0, G_MAXFLOAT,
+					    1.0, 10.0, 10.0 ));
+    widget = gtk_spin_button_new (adj, 1.0, 3);
+    gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(widget), TRUE);
+    gtk_widget_set_usize(widget, 80, -1);
+    break;
+  case PREF_COLOUR:
+    widget = dia_color_selector_new();
+    break;
+  case PREF_STRING:
+    widget = gtk_entry_new();
+    break;
+  case PREF_CHOICE: {
+    GtkWidget *menu;
+    GList *names;
+    GSList *group = NULL;
+    widget = gtk_option_menu_new();
+    menu = gtk_menu_new();
+    for (names = (data->choice_list_function)(); names != NULL;
+	 names = g_list_next(names)) {
+      GtkWidget *menuitem =
+	gtk_radio_menu_item_new_with_label(group, (gchar *)names->data);
+      gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
+      group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(menuitem));
+    }
+    gtk_option_menu_set_menu(GTK_OPTION_MENU(widget), menu);
+    gtk_widget_show_all(menu);
+    break;
+  }
+  case PREF_NONE:
+  case PREF_END_GROUP:
+    widget = NULL;
+    break;
+  }
+  if (widget != NULL)
+    gtk_widget_show(widget);
+  return widget;
+}
+
+static gint
+prefs_respond(GtkWidget *widget, 
+                   gint       response_id,
+                   gpointer   data)
+{
+  if (   response_id == GTK_RESPONSE_APPLY 
+      || response_id == GTK_RESPONSE_OK) {
+    prefs_update_prefs_from_dialog();
+    prefs_save();
+    diagram_redraw_all();
+  }
+
+  if (response_id != GTK_RESPONSE_APPLY)
+    gtk_widget_hide(widget);
+
+  return 0;
+}
+
+static void
+prefs_create_dialog(void)
+{
+  GtkWidget *label;
+  GtkWidget *dialog_vbox;
+  GtkWidget *notebook;
+  GtkTable *top_table = NULL; /* top level table for the tab */
+  GtkTable *current_table = NULL;
+  int i;
+  int tab_idx = -1;
+
+  if (prefs_dialog != NULL)
+    return;
+
+  prefs_dialog = gtk_dialog_new_with_buttons(
+			_("Preferences"),
+			GTK_WINDOW(interface_get_toolbox_shell()),
+			GTK_DIALOG_DESTROY_WITH_PARENT,
+			GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
+			GTK_STOCK_APPLY, GTK_RESPONSE_APPLY,
+			GTK_STOCK_OK, GTK_RESPONSE_OK,
+			NULL);
+  gtk_dialog_set_default_response (GTK_DIALOG(prefs_dialog), GTK_RESPONSE_OK);
+  gtk_window_set_resizable (GTK_WINDOW (prefs_dialog), TRUE);
+
+  dialog_vbox = GTK_DIALOG (prefs_dialog)->vbox;
+  
+  gtk_window_set_role (GTK_WINDOW (prefs_dialog), "preferences_window");
+
+  g_signal_connect(G_OBJECT (prefs_dialog), "response",
+                   G_CALLBACK (prefs_respond), NULL);
+
+  gtk_signal_connect (GTK_OBJECT (prefs_dialog), "delete_event",
+		      GTK_SIGNAL_FUNC(gtk_widget_hide), NULL);
+  gtk_signal_connect (GTK_OBJECT (prefs_dialog), "destroy",
+		      GTK_SIGNAL_FUNC(gtk_widget_destroyed), &prefs_dialog);
+
+  notebook = gtk_notebook_new ();
+  gtk_notebook_set_tab_pos (GTK_NOTEBOOK (notebook), GTK_POS_TOP);
+  gtk_box_pack_start (GTK_BOX (dialog_vbox), notebook, TRUE, TRUE, 0);
+  gtk_container_set_border_width (GTK_CONTAINER (notebook), 2);
+  gtk_widget_show (notebook);
+
+  for (i=0;i<NUM_PREFS_TABS;i++) {
+    GtkWidget *table;
+    GtkWidget *notebook_page;
+
+    label = gtk_label_new(gettext(prefs_tabs[i].title));
+    gtk_widget_show(label);
+
+    table = gtk_table_new (9, 2, FALSE);
+    prefs_tabs[i].table = GTK_TABLE(table);
+    gtk_widget_set_size_request(table, -1, -1);
+    gtk_widget_show(table);
+    
+#ifdef SCROLLED_PAGES
+    notebook_page = gtk_scrolled_window_new (NULL, NULL);
+    gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (notebook_page),
+				    GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+    gtk_widget_show(notebook_page);
+#else
+    notebook_page = table;
+#endif/* SCROLLED_PAGES */
+
+    gtk_notebook_append_page(GTK_NOTEBOOK(notebook), notebook_page, label);
+
+#ifdef SCROLLED_PAGES
+    gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(notebook_page),
+					  table);
+    gtk_viewport_set_shadow_type(GTK_VIEWPORT(GTK_BIN(notebook_page)->child),
+				 GTK_SHADOW_NONE);
+#endif /* SCROLLED_PAGES */
+
+  }
+
+  tab_idx = -1;
+  for (i=0;i<NUM_PREFS_DATA;i++) {
+    GtkWidget *widget = NULL;
+    int row;
+
+    if (prefs_data[i].hidden) 
+      continue;
+
+    if (tab_idx != prefs_data[i].tab) {
+      tab_idx = prefs_data[i].tab;
+      top_table = prefs_tabs[prefs_data[i].tab].table;
+      current_table = top_table;
+    }
+    row = prefs_tabs[tab_idx].row++;
+    switch(prefs_data[i].type) {
+    case PREF_NONE:
+      widget = gtk_frame_new(gettext(prefs_data[i].label_text));
+      gtk_widget_show (widget);
+      gtk_table_attach (current_table, widget, 0, 2,
+			row, row + 1,
+			GTK_FILL, GTK_FILL, 1, 1);
+      current_table = GTK_TABLE(gtk_table_new (9, 2, FALSE));
+      gtk_container_add(GTK_CONTAINER(widget), GTK_WIDGET(current_table));
+      gtk_widget_show(GTK_WIDGET(current_table));
+      break;
+    case PREF_END_GROUP:
+      current_table = top_table;
+      break;
+    case PREF_BOOLEAN:
+      widget = gtk_check_button_new_with_label (gettext(prefs_data[i].label_text));
+      gtk_widget_show (widget);
+      gtk_table_attach (current_table, widget, 0, 2,
+			row, row + 1,
+			GTK_FILL, GTK_FILL, 1, 1);
+      break;
+    default:
+      label = gtk_label_new (gettext(prefs_data[i].label_text));
+      gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.3);
+      gtk_widget_show (label);
+      
+      gtk_table_attach (current_table, label, 0, 1,
+			row, row + 1,
+			GTK_FILL, GTK_FILL, 1, 1);
+      
+      widget = prefs_get_property_widget(&prefs_data[i]);
+      if (widget != NULL) {
+	gtk_table_attach (current_table, widget, 1, 2,
+			  row, row + 1,
+			  GTK_FILL, GTK_FILL, 1, 1);
+      }
+      break;
+    }
+    prefs_data[i].widget = widget;
+    
+  }
+
+  gtk_widget_show (prefs_dialog);
+}
+
+static void
+prefs_update_prefs_from_dialog(void)
+{
+  GtkWidget *widget;
+  int i;
+  char *ptr;
+  
+  for (i=0;i<NUM_PREFS_DATA;i++) {
+    if (prefs_data[i].hidden) continue;
+    widget = prefs_data[i].widget;
+    ptr = (char *)&prefs + prefs_data[i].offset;
+    
+    prefs_get_value_from_widget(widget, &prefs_data[i],  ptr);
+  }
+}
+
+static void
+prefs_update_dialog_from_prefs(void)
+{
+  GtkWidget *widget;
+  int i;
+  char *ptr;
+  
+  for (i=0;i<NUM_PREFS_DATA;i++) {
+    if (prefs_data[i].hidden) continue;
+    widget = prefs_data[i].widget;
+    ptr = (char *)&prefs + prefs_data[i].offset;
+    
+    prefs_set_value_in_widget(widget, &prefs_data[i],  ptr);
+  }
+}
diff -Nuar cvs-dia/app/preferences.h dia/app/preferences.h
--- cvs-dia/app/preferences.h	2003-08-23 08:28:18.000000000 +0200
+++ dia/app/preferences.h	2003-08-30 19:39:50.000000000 +0200
@@ -34,6 +34,8 @@
     real x;
     real y;
     int major_lines;
+    int hex;
+    real w;
   } grid;
   
   struct {
diff -Nuar cvs-dia/app/preferences.h.orig dia/app/preferences.h.orig
--- cvs-dia/app/preferences.h.orig	1970-01-01 01:00:00.000000000 +0100
+++ dia/app/preferences.h.orig	2003-08-30 19:39:04.000000000 +0200
@@ -0,0 +1,77 @@
+/* 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.
+ */
+#ifndef PREFERENCES_H
+#define PREFERENCES_H
+
+#include "geometry.h"
+#include "color.h"
+#include "diagram_tree_window.h"
+#include "diagramdata.h"
+
+#define DEFAULT_GRID_COLOR { 0.85, .90, .90 }
+#define DEFAULT_PAGEBREAK_COLOR { 0.0, 0.0, 0.6 }
+
+struct DiaPreferences {
+  struct {
+    int visible;
+    int snap;
+    gboolean dynamic;
+    real x;
+    real y;
+    int major_lines;
+  } grid;
+  
+  struct {
+    int width;
+    int height;
+    real zoom;
+    int use_menu_bar;
+  } new_view;
+
+  NewDiagramData new_diagram;
+
+  int show_cx_pts;
+  int reset_tools_after_create;
+  int undo_depth;
+  int reverse_rubberbanding_intersects;
+  guint recent_documents_list_size;
+  
+  struct {
+    int visible;
+    int solid;
+  } pagebreak;
+
+  int render_bounding_boxes;
+  int prefer_psprint;
+    
+  int toolbox_on_top;
+  int recent_sheet;
+
+  DiagramTreeConfig dia_tree;
+};
+
+extern struct DiaPreferences prefs;
+
+void prefs_show(void);
+void prefs_set_defaults(void);
+void prefs_save(void);
+void prefs_load(void);
+
+#endif /* DIA_IMAGE_H */
+
+
diff -Nuar cvs-dia/doc/CVS/Entries dia/doc/CVS/Entries
--- cvs-dia/doc/CVS/Entries	2003-08-30 19:00:43.000000000 +0200
+++ dia/doc/CVS/Entries	2003-08-30 19:39:50.000000000 +0200
@@ -4,4 +4,5 @@
 /diagram.dtd/1.3/Thu Jul 11 02:09:21 2002//
 /shape.dtd/1.3/Thu Jul 11 02:09:21 2002//
 /sheet.dtd/1.3/Tue Aug  1 15:19:41 2000//
-D
+D/en////
+D/pl////
diff -Nuar cvs-dia/doc/CVS/Entries.Log dia/doc/CVS/Entries.Log
--- cvs-dia/doc/CVS/Entries.Log	1970-01-01 01:00:00.000000000 +0100
+++ dia/doc/CVS/Entries.Log	2003-08-30 19:39:50.000000000 +0200
@@ -0,0 +1,2 @@
+A D/en////
+A D/pl////
diff -Nuar cvs-dia/doc/CVS/Entries.orig dia/doc/CVS/Entries.orig
--- cvs-dia/doc/CVS/Entries.orig	1970-01-01 01:00:00.000000000 +0100
+++ dia/doc/CVS/Entries.orig	2003-08-30 19:39:04.000000000 +0200
@@ -0,0 +1,7 @@
+/.cvsignore/1.1/Wed Feb 28 03:19:33 2001//
+/Makefile.am/1.3/Wed May 29 17:34:18 2002//
+/custom-shapes/1.6/Sat Jan  4 12:21:51 2003//
+/diagram.dtd/1.3/Thu Jul 11 02:09:21 2002//
+/shape.dtd/1.3/Thu Jul 11 02:09:21 2002//
+/sheet.dtd/1.3/Tue Aug  1 15:19:41 2000//
+D
diff -Nuar cvs-dia/doc/en/CVS/Entries dia/doc/en/CVS/Entries
--- cvs-dia/doc/en/CVS/Entries	2003-08-30 19:00:44.000000000 +0200
+++ dia/doc/en/CVS/Entries	2003-08-30 19:39:50.000000000 +0200
@@ -16,4 +16,4 @@
 /usage-objects-special.xml/1.1/Wed Apr  9 20:19:01 2003//
 /usage-objects.xml/1.1/Wed Apr  9 20:19:01 2003//
 /usage-quickstart.xml/1.1/Wed Apr  9 20:19:01 2003//
-D
+D/graphics////
diff -Nuar cvs-dia/doc/en/CVS/Entries.Log dia/doc/en/CVS/Entries.Log
--- cvs-dia/doc/en/CVS/Entries.Log	1970-01-01 01:00:00.000000000 +0100
+++ dia/doc/en/CVS/Entries.Log	2003-08-30 19:39:50.000000000 +0200
@@ -0,0 +1 @@
+A D/graphics////
diff -Nuar cvs-dia/doc/en/CVS/Entries.orig dia/doc/en/CVS/Entries.orig
--- cvs-dia/doc/en/CVS/Entries.orig	1970-01-01 01:00:00.000000000 +0100
+++ dia/doc/en/CVS/Entries.orig	2003-08-30 19:39:04.000000000 +0200
@@ -0,0 +1,19 @@
+/.cvsignore/1.1/Wed Feb 28 03:19:34 2001//
+/Makefile.am/1.7/Fri Apr 25 01:03:19 2003//
+/authors.xml/1.1/Wed Apr  9 20:19:01 2003//
+/dia-C.omf/1.1/Sun Mar 18 22:54:58 2001//
+/dia-manual.xml/1.2/Fri Apr 11 08:43:32 2003//
+/entities.xml/1.1/Wed Apr  9 20:19:01 2003//
+/intro.xml/1.1/Wed Apr  9 20:19:01 2003//
+/license.xml/1.1/Wed Apr  9 20:19:01 2003//
+/topic.dat/1.1/Wed Feb 28 03:19:34 2001//
+/usage-canvas.xml/1.1/Wed Apr  9 20:19:01 2003//
+/usage-customization.xml/1.1/Wed Apr  9 20:19:01 2003//
+/usage-layers.xml/1.1/Wed Apr  9 20:19:01 2003//
+/usage-loadsave.xml/1.1/Wed Apr  9 20:19:01 2003//
+/usage-objects-basic.xml/1.1/Wed Apr  9 20:19:01 2003//
+/usage-objects-selecting.xml/1.2/Fri Apr 11 08:43:32 2003//
+/usage-objects-special.xml/1.1/Wed Apr  9 20:19:01 2003//
+/usage-objects.xml/1.1/Wed Apr  9 20:19:01 2003//
+/usage-quickstart.xml/1.1/Wed Apr  9 20:19:01 2003//
+D
diff -Nuar cvs-dia/lib/CVS/Entries dia/lib/CVS/Entries
--- cvs-dia/lib/CVS/Entries	2003-08-30 19:00:46.000000000 +0200
+++ dia/lib/CVS/Entries	2003-08-30 19:39:50.000000000 +0200
@@ -127,4 +127,4 @@
 /utils.h/1.4/Fri Feb 23 14:52:15 2001//
 /widgets.c/1.72/Thu Jan 30 22:59:28 2003//
 /widgets.h/1.21/Tue Nov 26 18:47:00 2002//
-D
+D/pixmaps////
diff -Nuar cvs-dia/lib/CVS/Entries.Log dia/lib/CVS/Entries.Log
--- cvs-dia/lib/CVS/Entries.Log	1970-01-01 01:00:00.000000000 +0100
+++ dia/lib/CVS/Entries.Log	2003-08-30 19:39:50.000000000 +0200
@@ -0,0 +1 @@
+A D/pixmaps////
diff -Nuar cvs-dia/lib/CVS/Entries.orig dia/lib/CVS/Entries.orig
--- cvs-dia/lib/CVS/Entries.orig	1970-01-01 01:00:00.000000000 +0100
+++ dia/lib/CVS/Entries.orig	2003-08-30 19:39:05.000000000 +0200
@@ -0,0 +1,130 @@
+/.cvsignore/1.2/Mon Sep 14 01:37:36 1998//
+/Makefile.am/1.64/Wed Aug 13 05:55:08 2003//
+/arrows.c/1.26/Fri Apr  4 20:30:30 2003//
+/arrows.h/1.23/Fri Apr  4 20:30:30 2003//
+/attributes.c/1.10/Mon Aug 11 18:36:18 2003//
+/attributes.h/1.7/Sun Oct  6 18:55:14 2002//
+/autoroute.c/1.7/Mon Apr 21 20:24:43 2003//
+/autoroute.h/1.3/Sat Apr 19 14:54:11 2003//
+/bezier_conn.c/1.28/Wed Aug 20 05:52:16 2003//
+/bezier_conn.h/1.17/Wed Aug 20 05:52:16 2003//
+/beziershape.c/1.20/Wed Aug 20 05:52:16 2003//
+/beziershape.h/1.10/Wed Aug 20 05:52:16 2003//
+/boundingbox.c/1.4/Sun May 27 18:46:35 2001//
+/boundingbox.h/1.3/Tue Oct  8 02:23:51 2002//
+/color.c/1.7/Fri Jul 18 23:00:26 2003//
+/color.h/1.8/Tue Oct  8 02:23:51 2002//
+/connection.c/1.12/Wed Aug 20 05:52:16 2003//
+/connection.h/1.10/Wed Aug 20 05:52:16 2003//
+/connectionpoint.c/1.2/Fri Aug 15 13:48:22 2003//
+/connectionpoint.h/1.9/Fri Aug 15 13:48:22 2003//
+/connpoint_line.c/1.8/Thu Aug 14 21:36:26 2003//
+/connpoint_line.h/1.5/Sun Jun 10 21:11:13 2001//
+/create.h/1.2/Tue Oct  8 02:23:51 2002//
+/dia-enums.h/1.1/Sun Oct  6 18:55:14 2002//
+/dia_dirs.c/1.11/Fri Apr 25 16:34:48 2003//
+/dia_dirs.h/1.3/Tue Apr  8 17:32:00 2003//
+/dia_image.c/1.21/Wed Jan 15 19:05:30 2003//
+/dia_image.h/1.12/Wed Jan 15 14:50:36 2003//
+/dia_svg.c/1.3/Thu Apr 24 18:30:48 2003//
+/dia_svg.h/1.1/Sat Oct 12 14:01:05 2002//
+/dia_xml.c/1.45/Sun Dec  8 00:51:55 2002//
+/dia_xml.h/1.12/Sun Dec  8 00:51:55 2002//
+/dia_xml_libxml.h/1.3/Sat Jun  8 13:30:22 2002//
+/diagdkrenderer.c/1.7/Wed Nov 27 20:38:43 2002//
+/diagdkrenderer.h/1.2/Tue Oct  8 02:23:51 2002//
+/diagramdata.c/1.41/Mon Aug 25 21:44:37 2003//
+/diagramdata.h/1.32/Mon Aug 25 17:34:09 2003//
+/diagtkfontsel.c/1.2/Sat Dec  7 11:10:54 2002//
+/diagtkfontsel.h/1.1/Mon Nov 25 01:32:46 2002//
+/diainteractiverenderer.c/1.2/Sun Oct  6 23:46:46 2002//
+/dialibartrenderer.c/1.13/Wed Aug 13 21:13:51 2003//
+/dialibartrenderer.h/1.3/Sat Jan 25 19:26:24 2003//
+/diamenu.h/1.6/Tue Oct  8 02:23:51 2002//
+/diarenderer.c/1.5/Fri Feb 28 20:02:09 2003//
+/diarenderer.h/1.2/Tue Oct  8 02:23:51 2002//
+/diasvgrenderer.c/1.5/Tue Apr 22 20:21:01 2003//
+/diasvgrenderer.h/1.2/Tue Oct  8 02:23:51 2002//
+/diatransform.c/1.3/Tue Oct  8 21:19:51 2002//
+/diatransform.h/1.3/Tue Oct  8 02:23:51 2002//
+/diatypes.h/1.2/Thu Dec  5 23:47:53 2002//
+/diavar.h/1.2/Fri Nov 17 14:57:31 2000//
+/dummy_dep.h/1.22/Wed Aug 20 05:52:16 2003//
+/dynamic_obj.c/1.1/Wed Sep 25 23:44:46 2002//
+/dynamic_obj.h/1.1/Wed Sep 25 23:44:46 2002//
+/element.c/1.10/Wed Aug 20 05:52:16 2003//
+/element.h/1.10/Wed Aug 20 05:52:16 2003//
+/filter.c/1.6/Sun Feb 16 07:04:31 2003//
+/filter.h/1.7/Tue Oct  8 02:23:51 2002//
+/focus.c/1.3/Fri Mar 23 14:29:49 2001//
+/focus.h/1.7/Tue Oct  8 02:23:51 2002//
+/font.c/1.106/Tue Jan 21 13:43:09 2003//
+/font.h/1.30/Mon Nov 18 23:20:34 2002//
+/geometry.c/1.15/Sun Dec  8 16:27:27 2002//
+/geometry.h/1.23/Wed Apr  9 18:37:35 2003//
+/group.c/1.3/Thu Jul 31 11:21:49 2003//
+/group.h/1.2/Sat Dec  7 11:10:55 2002//
+/handle.h/1.5/Tue Oct  8 02:23:51 2002//
+/intl.c/1.6/Mon Sep 23 19:27:44 2002//
+/intl.h/1.6/Mon Sep 23 19:27:44 2002//
+/libdia.def/1.38/Thu Aug 21 18:07:47 2003//
+/makefile.mingw/1.4/Wed Apr  9 18:37:35 2003//
+/makefile.msc/1.25/Thu Aug 21 18:07:47 2003//
+/message.c/1.24/Thu Jan 23 22:45:51 2003//
+/message.h/1.5/Wed Jun 12 18:49:04 2002//
+/neworth_conn.c/1.12/Wed Aug 20 05:52:16 2003//
+/neworth_conn.h/1.10/Wed Aug 20 05:52:16 2003//
+/objchange.c/1.3/Fri Mar 23 14:29:49 2001//
+/objchange.h/1.3/Tue Oct  8 02:23:51 2002//
+/object.c/1.27/Fri Aug 15 14:42:03 2003//
+/object.h/1.42/Wed Aug 20 05:52:16 2003//
+/object_defaults.c/1.7/Wed Aug 20 05:52:16 2003//
+/orth_conn.c/1.26/Wed Aug 20 05:52:16 2003//
+/orth_conn.h/1.20/Wed Aug 20 05:52:16 2003//
+/paper.c/1.14/Mon Sep  9 12:35:17 2002//
+/paper.h/1.5/Tue Oct  8 02:23:51 2002//
+/parent.c/1.1/Sun Jul 13 20:11:20 2003//
+/parent.h/1.1/Sun Jul 13 20:11:20 2003//
+/plug-ins.c/1.31/Sun Feb 16 07:04:31 2003//
+/plug-ins.h/1.9/Tue Oct  8 02:23:51 2002//
+/poly_conn.c/1.16/Wed Aug 20 05:52:16 2003//
+/poly_conn.h/1.12/Wed Aug 20 05:52:16 2003//
+/polyshape.c/1.20/Wed Aug 20 05:52:16 2003//
+/polyshape.h/1.10/Wed Aug 20 05:52:16 2003//
+/prop_attr.c/1.6/Sun Oct  6 18:55:14 2002//
+/prop_attr.h/1.2/Sat Jun  8 13:30:22 2002//
+/prop_basic.c/1.5/Mon Apr 29 22:16:35 2002//
+/prop_basic.h/1.2/Sat Jun  8 13:30:22 2002//
+/prop_geomtypes.c/1.5/Sun Aug  3 15:27:05 2003//
+/prop_geomtypes.h/1.2/Sat Jun  8 13:30:22 2002//
+/prop_inttypes.c/1.6/Sun Jun  9 16:41:56 2002//
+/prop_inttypes.h/1.3/Sat Jun  8 13:30:22 2002//
+/prop_sdarray.c/1.1/Mon Aug 13 07:24:25 2001//
+/prop_sdarray.h/1.2/Sat Jun  8 13:30:22 2002//
+/prop_text.c/1.10/Mon Aug 25 21:44:37 2003//
+/prop_text.h/1.3/Sun Jan 19 16:38:21 2003//
+/prop_widgets.c/1.7/Mon Apr 14 02:59:07 2003//
+/prop_widgets.h/1.4/Wed Nov 27 17:26:55 2002//
+/propdesc.c/1.3/Tue Aug 14 10:54:38 2001//
+/propdialogs.c/1.8/Mon Aug 25 22:06:44 2003//
+/properties.c/1.35/Mon Aug 13 07:24:25 2001//
+/properties.h/1.49/Tue Jul  1 20:30:38 2003//
+/propinternals.h/1.4/Wed Nov 27 19:38:43 2002//
+/proplist.c/1.9/Tue Jul  1 20:30:38 2003//
+/propobject.c/1.9/Mon Sep 23 19:27:44 2002//
+/propoffsets.c/1.2/Tue Aug 14 10:54:38 2001//
+/propregistry.c/1.1/Mon Aug 13 07:24:25 2001//
+/ps-utf8.c/1.10/Sun Jun  9 16:41:56 2002//
+/ps-utf8.h/1.5/Tue Oct  8 02:23:51 2002//
+/render.c/1.14/Mon Sep 23 19:27:44 2002//
+/render.h/1.25/Sun Oct  6 18:55:14 2002//
+/sheet.c/1.23/Tue Sep 24 23:29:39 2002//
+/sheet.h/1.8/Tue Oct  8 02:23:51 2002//
+/text.c/1.49/Fri Dec  6 23:07:31 2002//
+/text.h/1.18/Tue Oct  8 02:23:51 2002//
+/textattr.h/1.3/Tue Oct  8 02:23:51 2002//
+/utils.c/1.4/Thu Jun  7 22:16:20 2001//
+/utils.h/1.4/Fri Feb 23 14:52:15 2001//
+/widgets.c/1.72/Thu Jan 30 22:59:28 2003//
+/widgets.h/1.21/Tue Nov 26 18:47:00 2002//
+D
diff -Nuar cvs-dia/lib/diagramdata.c dia/lib/diagramdata.c
--- cvs-dia/lib/diagramdata.c	2003-08-25 23:44:37.000000000 +0200
+++ dia/lib/diagramdata.c	2003-08-30 19:39:50.000000000 +0200
@@ -50,6 +50,7 @@
 	data->grid.dynamic = TRUE;
 	data->grid.width_x = 1.0;
 	data->grid.width_y = 1.0;
+	data->grid.width_w = 1.0;
 	data->grid.visible_x = 1;
 	data->grid.visible_y = 1;
 	data->grid.colour = prefs->grid_color;
diff -Nuar cvs-dia/lib/diagramdata.c.orig dia/lib/diagramdata.c.orig
--- cvs-dia/lib/diagramdata.c.orig	1970-01-01 01:00:00.000000000 +0100
+++ dia/lib/diagramdata.c.orig	2003-08-30 19:39:05.000000000 +0200
@@ -0,0 +1,716 @@
+/* Dia -- an diagram creation/manipulation program
+ * Copyright (C) 1998 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
+
+#include "intl.h"
+#include "diagramdata.h"
+#include "diarenderer.h"
+#include "paper.h"
+#include "dynamic_obj.h"
+
+static const Rectangle invalid_extents = { -1.0,-1.0,-1.0,-1.0 };
+static void set_parent_layer(gpointer layer, gpointer object);
+
+DiagramData *
+new_diagram_data (NewDiagramData *prefs)
+{
+	DiagramData *data;
+	Layer *first_layer;
+   
+	data = g_new (DiagramData, 1);
+   
+	data->extents.left = 0.0; 
+	data->extents.right = 10.0; 
+	data->extents.top = 0.0; 
+	data->extents.bottom = 10.0; 
+ 
+	data->bg_color = prefs->bg_color;
+	data->pagebreak_color = prefs->pagebreak_color;
+
+	get_paper_info (&data->paper, -1, prefs);
+
+	data->grid.dynamic = TRUE;
+	data->grid.width_x = 1.0;
+	data->grid.width_y = 1.0;
+	data->grid.visible_x = 1;
+	data->grid.visible_y = 1;
+	data->grid.colour = prefs->grid_color;
+
+	data->guides.nhguides = 0;
+	data->guides.hguides = NULL;
+	data->guides.nvguides = 0;
+	data->guides.vguides = NULL;
+
+	first_layer = new_layer(g_strdup(_("Background")),data);
+  
+	data->layers = g_ptr_array_new ();
+	g_ptr_array_add (data->layers, first_layer);
+	data->active_layer = first_layer;
+
+	data->selected_count = 0;
+	data->selected = NULL;
+  
+	data->is_compressed = prefs->compress_save; // Overridden by doc
+
+	return data;
+}
+
+void
+diagram_data_destroy(DiagramData *data)
+{
+  int i;
+
+  g_free(data->paper.name);
+
+  for (i=0;i<data->layers->len;i++) {
+    layer_destroy(g_ptr_array_index(data->layers, i));
+  }
+  g_ptr_array_free(data->layers, TRUE);
+  data->active_layer = NULL;
+
+  g_list_free(data->selected);
+  data->selected = NULL; /* for safety */
+  data->selected_count = 0;
+  g_free(data);
+}
+
+Layer *
+new_layer(gchar *name, DiagramData *parent)
+{
+  Layer *layer;
+
+  layer = g_new(Layer, 1);
+
+  layer->name = name;
+
+  layer->parent_diagram = parent;
+  layer->visible = TRUE;
+
+  layer->objects = NULL;
+
+  layer->extents.left = 0.0; 
+  layer->extents.right = 10.0; 
+  layer->extents.top = 0.0; 
+  layer->extents.bottom = 10.0; 
+  
+  return layer;
+}
+
+void
+layer_destroy(Layer *layer)
+{
+  g_free(layer->name);
+  destroy_object_list(layer->objects);
+  g_free(layer);
+}
+
+void
+data_raise_layer(DiagramData *data, Layer *layer)
+{
+  int i;
+  int layer_nr = -1;
+  Layer *tmp;
+  
+  for (i=0;i<data->layers->len;i++) {
+    if (g_ptr_array_index(data->layers, i)==layer)
+      layer_nr = i;
+  }
+
+  g_assert(layer_nr>=0);
+
+  if (layer_nr < data->layers->len-1) {
+    tmp = g_ptr_array_index(data->layers, layer_nr+1);
+    g_ptr_array_index(data->layers, layer_nr+1) =
+      g_ptr_array_index(data->layers, layer_nr);
+    g_ptr_array_index(data->layers, layer_nr) = tmp;
+  }
+}
+
+void
+data_lower_layer(DiagramData *data, Layer *layer)
+{
+  int i;
+  int layer_nr = -1;
+  Layer *tmp;
+  
+  for (i=0;i<data->layers->len;i++) {
+    if (g_ptr_array_index(data->layers, i)==layer)
+      layer_nr = i;
+  }
+
+  g_assert(layer_nr>=0);
+
+  if (layer_nr > 0) {
+    tmp = g_ptr_array_index(data->layers, layer_nr-1);
+    g_ptr_array_index(data->layers, layer_nr-1) =
+      g_ptr_array_index(data->layers, layer_nr);
+    g_ptr_array_index(data->layers, layer_nr) = tmp;
+  }
+}
+
+
+void
+data_add_layer(DiagramData *data, Layer *layer)
+{
+  g_ptr_array_add(data->layers, layer);
+  layer->parent_diagram = data;
+  layer_update_extents(layer);
+  data_update_extents(data);
+}
+void
+data_add_layer_at(DiagramData *data, Layer *layer, int pos)
+{
+  int len;
+  int i;
+  
+  g_ptr_array_add(data->layers, layer);
+  len = data->layers->len;
+
+  if ( (pos>=0) && (pos < len)) {
+    for (i=len-1;i>pos;i--) {
+      g_ptr_array_index(data->layers, i) = g_ptr_array_index(data->layers, i-1);
+    }
+    g_ptr_array_index(data->layers, pos) = layer;
+  }
+  
+  layer->parent_diagram = data;
+  layer_update_extents(layer);
+  data_update_extents(data);
+}
+
+void
+data_set_active_layer(DiagramData *data, Layer *layer)
+{
+  data->active_layer = layer;
+}
+
+void
+data_delete_layer(DiagramData *data, Layer *layer)
+{
+  if (data->layers->len<=1)
+    return;
+
+  if (data->active_layer == layer) {
+    data_remove_all_selected(data);
+  }
+  layer->parent_diagram = NULL;
+  g_ptr_array_remove(data->layers, layer);
+
+  if (data->active_layer == layer) {
+    data->active_layer = g_ptr_array_index(data->layers, 0);
+  }
+}
+
+void
+data_select(DiagramData *data, Object *obj)
+{
+  data->selected = g_list_prepend(data->selected, obj);
+  data->selected_count++;
+}
+
+void
+data_unselect(DiagramData *data, Object *obj)
+{
+  data->selected = g_list_remove(data->selected, obj);
+  data->selected_count--;
+}
+
+void
+data_remove_all_selected(DiagramData *data)
+{
+  g_list_free(data->selected); /* Remove previous selection */
+  data->selected_count = 0;
+  data->selected = NULL;
+}
+
+static gboolean
+data_has_visible_layers(DiagramData *data)
+{
+  guint i;
+  for (i = 0; i < data->layers->len; i++) {
+    Layer *layer = g_ptr_array_index(data->layers, i);
+    if (layer->visible) return TRUE;
+  }
+  return FALSE;
+}
+
+static void
+data_get_layers_extents_union(DiagramData *data) {
+  guint i;
+  gboolean first = TRUE;
+  Rectangle new_extents;
+
+  for ( i = 0 ; i<data->layers->len; i++) {
+    Layer *layer = g_ptr_array_index(data->layers, i);    
+    if (!layer->visible) continue;
+    
+    layer_update_extents(layer);
+
+    if (first) {
+      new_extents = layer->extents;
+      first = rectangle_equals(&new_extents,&invalid_extents);
+    } else {
+      if (!rectangle_equals(&layer->extents,&invalid_extents)) {
+        rectangle_union(&new_extents, &layer->extents);
+      }
+    }
+  }
+
+  data->extents = new_extents;
+}
+
+static void
+data_adapt_scaling_to_extents(DiagramData *data)
+{
+  gdouble pwidth = data->paper.width * data->paper.scaling;
+  gdouble pheight = data->paper.height * data->paper.scaling;
+
+  gdouble xscale = data->paper.fitwidth * pwidth /
+    (data->extents.right - data->extents.left);
+  gdouble yscale = data->paper.fitheight * pheight /
+    (data->extents.bottom - data->extents.top);
+  
+  data->paper.scaling = MIN(xscale, yscale);
+  data->paper.width  = pwidth  / data->paper.scaling;
+  data->paper.height = pheight / data->paper.scaling;
+}
+
+static gboolean
+data_compute_extents(DiagramData *data) 
+{
+  Rectangle old_extents = data->extents;
+
+  if (!data_has_visible_layers(data)) {   
+    if (data->layers->len > 0) {
+      Layer *layer = g_ptr_array_index(data->layers, 0);    
+      layer_update_extents(layer);
+      
+      data->extents = layer->extents;
+    } else {
+      data->extents = invalid_extents;
+    }
+  } else {
+    data_get_layers_extents_union(data);
+  }
+
+  if (rectangle_equals(&data->extents,&invalid_extents)) {
+      data->extents.left = 0.0;
+      data->extents.right = 10.0;
+      data->extents.top = 0.0;
+      data->extents.bottom = 10.0;
+  }
+  return (!rectangle_equals(&data->extents,&old_extents));
+}
+
+gboolean
+data_update_extents(DiagramData *data)
+{
+
+  gboolean changed;
+
+  changed = data_compute_extents(data);
+  if (changed && data->paper.fitto) data_adapt_scaling_to_extents(data);
+
+  return changed;
+}
+
+GList *
+data_get_sorted_selected(DiagramData *data)
+{
+  GList *list;
+  GList *sorted_list;
+  GList *found;
+  Object *obj;
+
+  if (data->selected_count == 0)
+    return NULL;
+  
+  sorted_list = NULL;
+  list = g_list_last(data->active_layer->objects);
+  while (list != NULL) {
+    found = g_list_find(data->selected, list->data);
+    if (found) {
+      obj = (Object *)found->data;
+      sorted_list = g_list_prepend(sorted_list, obj);
+    }
+    list = g_list_previous(list);
+  }
+
+  return sorted_list;
+}
+
+GList *
+data_get_sorted_selected_remove(DiagramData *data)
+{
+  GList *list,*tmp;
+  GList *sorted_list;
+  GList *found;
+  Object *obj;
+  
+  if (data->selected_count == 0)
+    return NULL;
+  
+  sorted_list = NULL;
+  list = g_list_last(data->active_layer->objects);
+  while (list != NULL) {
+    found = g_list_find(data->selected, list->data);
+    if (found) {
+      obj = (Object *)found->data;
+      sorted_list = g_list_prepend(sorted_list, obj);
+
+      tmp = list;
+      list = g_list_previous(list);
+      data->active_layer->objects =
+	g_list_remove_link(data->active_layer->objects, tmp);
+    } else {
+      list = g_list_previous(list);
+    }
+  }
+
+  return sorted_list;
+}
+
+void
+data_render(DiagramData *data, DiaRenderer *renderer, Rectangle *update,
+	    ObjectRenderer obj_renderer /* Can be NULL */,
+	    gpointer gdata)
+{
+  Layer *layer;
+  int i;
+  int active_layer;
+
+  if (!renderer->is_interactive) (DIA_RENDERER_GET_CLASS(renderer)->begin_render)(renderer);
+  
+  for (i=0; i<data->layers->len; i++) {
+    layer = (Layer *) g_ptr_array_index(data->layers, i);
+    active_layer = (layer == data->active_layer);
+    if (layer->visible)
+      layer_render(layer, renderer, update, obj_renderer, gdata, active_layer);
+  }
+  
+  if (!renderer->is_interactive) (DIA_RENDERER_GET_CLASS(renderer)->end_render)(renderer);
+}
+
+static void
+normal_render(Object *obj, DiaRenderer *renderer,
+	      int active_layer,
+	      gpointer data)
+{
+  DIA_RENDERER_GET_CLASS(renderer)->draw_object(renderer, obj);
+}
+
+
+int render_bounding_boxes = FALSE;
+
+/* If obj_renderer is NULL normal_render is used. */
+void
+layer_render(Layer *layer, DiaRenderer *renderer, Rectangle *update,
+	     ObjectRenderer obj_renderer,
+	     gpointer data,
+	     int active_layer)
+{
+  GList *list;
+  Object *obj;
+
+  if (obj_renderer == NULL)
+    obj_renderer = normal_render;
+  
+  /* Draw all objects: */
+  list = layer->objects;
+  while (list!=NULL) {
+    obj = (Object *) list->data;
+
+    if (update==NULL || rectangle_intersects(update, &obj->bounding_box)) {
+      if ((render_bounding_boxes) && (renderer->is_interactive)) {
+	Point p1, p2;
+	Color col;
+	p1.x = obj->bounding_box.left;
+	p1.y = obj->bounding_box.top;
+	p2.x = obj->bounding_box.right;
+	p2.y = obj->bounding_box.bottom;
+	col.red = 1.0;
+	col.green = 0.0;
+	col.blue = 1.0;
+
+        DIA_RENDERER_GET_CLASS(renderer)->set_linewidth(renderer,0.01);
+	DIA_RENDERER_GET_CLASS(renderer)->draw_rect(renderer, &p1, &p2, &col);
+      }
+      (*obj_renderer)(obj, renderer, active_layer, data);
+    }
+    
+    list = g_list_next(list);
+  }
+}
+
+static void
+set_parent_layer(gpointer element, gpointer user_data) {
+  ((Object*)element)->parent_layer = (Layer*)user_data;
+}
+
+int
+layer_object_index(Layer *layer, Object *obj)
+{
+  return (int)g_list_index(layer->objects, (gpointer) obj);
+}
+
+void
+layer_add_object(Layer *layer, Object *obj)
+{
+  layer->objects = g_list_append(layer->objects, (gpointer) obj);
+  set_parent_layer(obj, layer);
+}
+
+void
+layer_add_object_at(Layer *layer, Object *obj, int pos)
+{
+  layer->objects = g_list_insert(layer->objects, (gpointer) obj, pos);
+  set_parent_layer(obj, layer);
+}
+
+void
+layer_add_objects(Layer *layer, GList *obj_list)
+{
+  layer->objects = g_list_concat(layer->objects, obj_list);
+  g_list_foreach(obj_list, set_parent_layer, layer);
+}
+
+void
+layer_add_objects_first(Layer *layer, GList *obj_list)
+{
+  layer->objects = g_list_concat(obj_list, layer->objects);
+  g_list_foreach(obj_list, set_parent_layer, layer);
+}
+
+void
+layer_remove_object(Layer *layer, Object *obj)
+{
+  layer->objects = g_list_remove(layer->objects, obj);
+  dynobj_list_remove_object(obj);
+  set_parent_layer(obj, NULL);
+}
+
+void
+layer_remove_objects(Layer *layer, GList *obj_list)
+{
+  Object *obj;
+  while (obj_list != NULL) {
+    obj = (Object *) obj_list->data;
+    
+    layer->objects = g_list_remove(layer->objects, obj);
+    
+    obj_list = g_list_next(obj_list);
+    dynobj_list_remove_object(obj);
+    set_parent_layer(obj, NULL);
+  }
+}
+
+
+GList *
+layer_find_objects_intersecting_rectangle(Layer *layer, Rectangle *rect)
+{
+  GList *list;
+  GList *selected_list;
+  Object *obj;
+
+  selected_list = NULL;
+  list = layer->objects;
+  while (list != NULL) {
+    obj = (Object *)list->data;
+
+    if (rectangle_intersects(rect, &obj->bounding_box)) {
+      selected_list = g_list_prepend(selected_list, obj);
+    }
+
+    list = g_list_next(list);
+  }
+
+  return selected_list;
+}
+
+GList *
+layer_find_objects_in_rectangle(Layer *layer, Rectangle *rect)
+{
+  GList *list;
+  GList *selected_list;
+  Object *obj;
+
+  selected_list = NULL;
+  list = layer->objects;
+  while (list != NULL) {
+    obj = (Object *)list->data;
+
+    if (rectangle_in_rectangle(rect, &obj->bounding_box)) {
+      selected_list = g_list_prepend(selected_list, obj);
+    }
+    
+    list = g_list_next(list);
+  }
+
+  return selected_list;
+}
+
+/** Find the object closest to the given point in the layer,
+ * no further away than maxdist, and not included in avoid.
+ * Stops it if finds an object that includes the point.
+ */
+Object *
+layer_find_closest_object_except(Layer *layer, Point *pos,
+				 real maxdist, GList *avoid)
+{
+  GList *l;
+  Object *closest;
+  Object *obj;
+  real dist;
+  GList *avoid_tmp;
+
+  closest = NULL;
+  
+  for (l = layer->objects; l!=NULL; l = g_list_next(l)) {
+    obj = (Object *) l->data;
+
+    /* Check bounding box here too. Might give speedup. */
+    dist = obj->ops->distance_from(obj, pos);
+
+    if (maxdist-dist > 0.00000001) {
+      for (avoid_tmp = avoid; avoid_tmp != NULL; avoid_tmp = avoid_tmp->next) {
+	if (avoid_tmp->data == obj) {
+	  goto NEXTOBJECT;
+	}
+      }
+      closest = obj;
+    }
+  NEXTOBJECT:
+  ;
+  }
+
+  return closest;
+}
+
+Object *
+layer_find_closest_object(Layer *layer, Point *pos, real maxdist)
+{
+  return layer_find_closest_object_except(layer, pos, maxdist, NULL);
+}
+
+
+real layer_find_closest_connectionpoint(Layer *layer,
+					ConnectionPoint **closest,
+					Point *pos,
+					Object *notthis)
+{
+  GList *l;
+  Object *obj;
+  ConnectionPoint *cp;
+  real mindist, dist;
+  int i;
+
+  mindist = 1000000.0; /* Realy big value... */
+  
+  *closest = NULL;
+  
+  for (l = layer->objects; l!=NULL; l = g_list_next(l) ) {
+    obj = (Object *) l->data;
+
+    if (obj == notthis) continue;
+    for (i=0;i<obj->num_connections;i++) {
+      cp = obj->connections[i];
+      /* Note: Uses manhattan metric for speed... */
+      dist = distance_point_point_manhattan(pos, &cp->pos);
+      if (dist<mindist) {
+	mindist = dist;
+	*closest = cp;
+      }
+    }
+    
+ }
+
+  return mindist;
+}
+
+int layer_update_extents(Layer *layer)
+{
+  GList *l;
+  Object *obj;
+  Rectangle new_extents;
+  
+  l = layer->objects;
+  if (l!=NULL) {
+    obj = (Object *) l->data;
+    new_extents = obj->bounding_box;
+    l = g_list_next(l);
+  
+    while(l!=NULL) {
+      obj = (Object *) l->data;
+      rectangle_union(&new_extents, &obj->bounding_box);
+      l = g_list_next(l);
+    }
+  } else {
+    new_extents = invalid_extents;
+  }
+
+  if (rectangle_equals(&new_extents,&layer->extents)) return FALSE;
+
+  layer->extents = new_extents;
+  return TRUE;
+}
+
+void
+layer_replace_object_with_list(Layer *layer, Object *remove_obj,
+			       GList *insert_list)
+{
+  GList *list;
+
+  list = g_list_find(layer->objects, remove_obj);
+
+  g_assert(list!=NULL);
+  set_parent_layer(remove_obj, NULL);
+  dynobj_list_remove_object(remove_obj);
+  g_list_foreach(insert_list, set_parent_layer, layer);
+
+  if (list->prev == NULL) {
+    layer->objects = insert_list;
+  } else {
+    list->prev->next = insert_list;
+    insert_list->prev = list->prev;
+  }
+  if (list->next != NULL) {
+    GList *last;
+    last = g_list_last(insert_list);
+    last->next = list->next;
+    list->next->prev = last;
+  }
+  g_list_free_1(list);
+}
+
+void layer_set_object_list(Layer *layer, GList *list)
+{
+  g_list_foreach(layer->objects, set_parent_layer, NULL);
+  g_list_foreach(layer->objects, dynobj_list_remove_object, NULL);
+  g_list_free(layer->objects);
+  layer->objects = list;
+  g_list_foreach(layer->objects, set_parent_layer, layer);
+}
+
+DiagramData *
+layer_get_parent_diagram(Layer *layer)
+{
+  return layer->parent_diagram;
+}
diff -Nuar cvs-dia/lib/diagramdata.h dia/lib/diagramdata.h
--- cvs-dia/lib/diagramdata.h	2003-08-25 19:34:09.000000000 +0200
+++ dia/lib/diagramdata.h	2003-08-30 19:39:51.000000000 +0200
@@ -50,7 +50,7 @@
 
   struct  {
     /* grid line intervals */
-    real width_x, width_y;
+    real width_x, width_y, width_w;
     /* the interval between visible grid lines */
     guint visible_x, visible_y;
     /* the interval between major lines (non-stippled).
diff -Nuar cvs-dia/lib/diagramdata.h.orig dia/lib/diagramdata.h.orig
--- cvs-dia/lib/diagramdata.h.orig	1970-01-01 01:00:00.000000000 +0100
+++ dia/lib/diagramdata.h.orig	2003-08-30 19:39:05.000000000 +0200
@@ -0,0 +1,167 @@
+/* Dia -- an diagram creation/manipulation program -*- c -*-
+ * Copyright (C) 1998 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.
+ */
+#ifndef DIAGRAMDATA_H
+#define DIAGRAMDATA_H
+
+#include <glib.h>
+
+#include "diatypes.h"
+/* #include "object.h" later after declaring types */
+#include "color.h"
+#include "geometry.h"
+#include "diavar.h"
+#include "paper.h"
+
+struct _NewDiagramData {
+  gchar *papertype;
+  gfloat tmargin, bmargin, lmargin, rmargin;
+  gboolean is_portrait;
+  gfloat scaling;
+  gboolean fitto;
+  gint fitwidth, fitheight;
+  Color bg_color, pagebreak_color, grid_color;
+  int compress_save;
+};
+
+struct _DiagramData {
+  Rectangle extents;      /* The extents of the diagram        */
+
+  Color bg_color;
+  Color pagebreak_color;
+
+  PaperInfo paper;       /* info about the page info for the diagram */
+  gboolean is_compressed; /* TRUE if by default it should be save compressed.
+			     The user can override this in Save As... */
+
+  struct  {
+    /* grid line intervals */
+    real width_x, width_y;
+    /* the interval between visible grid lines */
+    guint visible_x, visible_y;
+    /* the interval between major lines (non-stippled).
+     * if 0, no major lines are drawn (all lines are stippled).
+     * if 1, all lines are solid.
+     */
+    guint major_lines;
+    /* True if the grid is dynamically calculated.
+     * When true, width_x and width_y are ignored.
+     */
+    gboolean dynamic;
+    /* The color of the grid lines.
+     */
+    Color colour;
+  } grid;
+
+  struct {
+    /* sorted arrays of the guides for the diagram */
+    real *hguides, *vguides;
+    guint nhguides, nvguides;
+  } guides;
+
+  GPtrArray *layers;     /* Layers ordered by decreasing z-order */
+  Layer *active_layer;
+
+  guint selected_count;
+  GList *selected;        /* List of objects that are selected,
+			     all from the active layer! */
+};
+
+struct _Layer {
+  char *name;
+  Rectangle extents;      /* The extents of the layer        */
+
+  GList *objects;         /* List of objects in the layer,
+			     sorted by decreasing z-valued,
+			     objects can ONLY be connected to objects
+			     in the same layer! */
+
+  int visible;
+
+  DiagramData *parent_diagram; /* Back-pointer to the diagram.  This
+				  must only be set by functions internal
+				  to the diagram, and accessed via
+				  layer_get_parent_diagram() */
+};
+
+#include "object.h"
+#include "dynamic_obj.h"
+
+DIAVAR int render_bounding_boxes;
+
+DiagramData *new_diagram_data(NewDiagramData *prefs);
+void diagram_data_destroy(DiagramData *data);
+
+Layer *new_layer (char *name, DiagramData *parent);
+void layer_destroy(Layer *layer);
+
+void data_raise_layer(DiagramData *data, Layer *layer);
+void data_lower_layer(DiagramData *data, Layer *layer);
+
+void data_add_layer(DiagramData *data, Layer *layer);
+void data_add_layer_at(DiagramData *data, Layer *layer, int pos);
+void data_set_active_layer(DiagramData *data, Layer *layer);
+void data_delete_layer(DiagramData *data, Layer *layer);
+void data_select(DiagramData *data, Object *obj);
+void data_unselect(DiagramData *data, Object *obj);
+void data_remove_all_selected(DiagramData *data);
+gboolean data_update_extents(DiagramData *data); /* returns true if changed. */
+GList *data_get_sorted_selected(DiagramData *data);
+GList *data_get_sorted_selected_remove(DiagramData *data);
+
+typedef void (*ObjectRenderer)(Object *obj, DiaRenderer *renderer,
+			       int active_layer,
+			       gpointer data);
+void data_render(DiagramData *data, DiaRenderer *renderer, Rectangle *update,
+		 ObjectRenderer obj_renderer /* Can be NULL */,
+		 gpointer gdata);  
+void layer_render(Layer *layer, DiaRenderer *renderer, Rectangle *update,
+		  ObjectRenderer obj_renderer /* Can be NULL */,
+		  gpointer data,
+		  int active_layer);
+
+int layer_object_index(Layer *layer, Object *obj);
+void layer_add_object(Layer *layer, Object *obj);
+void layer_add_object_at(Layer *layer, Object *obj, int pos);
+void layer_add_objects(Layer *layer, GList *obj_list);
+void layer_add_objects_first(Layer *layer, GList *obj_list);
+void layer_remove_object(Layer *layer, Object *obj);
+void layer_remove_objects(Layer *layer, GList *obj_list);
+GList *layer_find_objects_intersecting_rectangle(Layer *layer, Rectangle*rect);
+GList *layer_find_objects_in_rectangle(Layer *layer, Rectangle *rect);
+Object *layer_find_closest_object(Layer *layer, Point *pos, real maxdist);
+Object *layer_find_closest_object_except(Layer *layer, Point *pos,
+					 real maxdist, GList *avoid);
+real layer_find_closest_connectionpoint(Layer *layer,
+					ConnectionPoint **closest,
+					Point *pos,
+					Object *notthis);
+int layer_update_extents(Layer *layer); /* returns true if changed. */
+void layer_replace_object_with_list(Layer *layer, Object *obj,
+				    GList *list);
+void layer_set_object_list(Layer *layer, GList *list);
+DiagramData *layer_get_parent_diagram(Layer *layer);
+/* Make sure all objects that are in the layer and not in the new
+   list eventually gets destroyed. */
+
+#endif /* DIAGRAMDATA_H */
+
+
+
+
+
+
diff -Nuar cvs-dia/objects/CVS/Entries dia/objects/CVS/Entries
--- cvs-dia/objects/CVS/Entries	2003-08-30 19:00:46.000000000 +0200
+++ dia/objects/CVS/Entries	2003-08-30 19:39:51.000000000 +0200
@@ -3,4 +3,17 @@
 /makefile.mingw/1.3/Sat Sep 28 16:22:22 2002//
 /makefile.msc/1.16/Thu Aug 21 18:12:55 2003//
 /objects.def/1.1/Fri Jan  5 16:39:55 2001//
-D
+D/EML////
+D/ER////
+D/FS////
+D/GRAFCET////
+D/Misc////
+D/SADT////
+D/UML////
+D/bondgraph////
+D/chronogram////
+D/custom////
+D/flowchart////
+D/network////
+D/standard////
+D/sybase////
diff -Nuar cvs-dia/objects/CVS/Entries.Log dia/objects/CVS/Entries.Log
--- cvs-dia/objects/CVS/Entries.Log	1970-01-01 01:00:00.000000000 +0100
+++ dia/objects/CVS/Entries.Log	2003-08-30 19:39:51.000000000 +0200
@@ -0,0 +1,14 @@
+A D/EML////
+A D/ER////
+A D/FS////
+A D/GRAFCET////
+A D/Misc////
+A D/SADT////
+A D/UML////
+A D/bondgraph////
+A D/chronogram////
+A D/custom////
+A D/flowchart////
+A D/network////
+A D/standard////
+A D/sybase////
diff -Nuar cvs-dia/objects/CVS/Entries.orig dia/objects/CVS/Entries.orig
--- cvs-dia/objects/CVS/Entries.orig	1970-01-01 01:00:00.000000000 +0100
+++ dia/objects/CVS/Entries.orig	2003-08-30 19:39:05.000000000 +0200
@@ -0,0 +1,6 @@
+/.cvsignore/1.2/Mon Sep 14 01:37:38 1998//
+/Makefile.am/1.16/Tue Nov 26 16:42:52 2002//
+/makefile.mingw/1.3/Sat Sep 28 16:22:22 2002//
+/makefile.msc/1.16/Thu Aug 21 18:12:55 2003//
+/objects.def/1.1/Fri Jan  5 16:39:55 2001//
+D
diff -Nuar cvs-dia/objects/EML/CVS/Entries dia/objects/EML/CVS/Entries
--- cvs-dia/objects/EML/CVS/Entries	2003-08-30 19:00:46.000000000 +0200
+++ dia/objects/EML/CVS/Entries	2003-08-30 19:39:51.000000000 +0200
@@ -15,4 +15,4 @@
 /process.c/1.4/Thu Jul 31 11:21:50 2003//
 /process.h/1.2/Mon Jun 11 15:25:30 2001//
 /process_dialog.c/1.1/Fri Apr 20 18:23:20 2001//
-D
+D/pixmaps////
diff -Nuar cvs-dia/objects/EML/CVS/Entries.Log dia/objects/EML/CVS/Entries.Log
--- cvs-dia/objects/EML/CVS/Entries.Log	1970-01-01 01:00:00.000000000 +0100
+++ dia/objects/EML/CVS/Entries.Log	2003-08-30 19:39:51.000000000 +0200
@@ -0,0 +1 @@
+A D/pixmaps////
diff -Nuar cvs-dia/objects/EML/CVS/Entries.orig dia/objects/EML/CVS/Entries.orig
--- cvs-dia/objects/EML/CVS/Entries.orig	1970-01-01 01:00:00.000000000 +0100
+++ dia/objects/EML/CVS/Entries.orig	2003-08-30 19:39:07.000000000 +0200
@@ -0,0 +1,18 @@
+/.cvsignore/1.1/Mon Apr 30 11:15:55 2001//
+/Makefile.am/1.4/Mon Sep  9 12:35:18 2002//
+/dbox.c/1.3/Wed May 16 13:35:25 2001//
+/dbox.h/1.2/Wed Jul 18 04:39:08 2001//
+/eml.c/1.2/Tue May  1 19:56:03 2001//
+/eml.h/1.1/Fri Apr 20 18:23:20 2001//
+/instantiation.c/1.7/Thu Jul 31 11:21:50 2003//
+/interaction-ortho.c/1.6/Thu Jul 31 11:21:50 2003//
+/interaction.c/1.5/Thu Jul 31 11:21:50 2003//
+/interaction.h/1.1/Fri Apr 20 18:23:20 2001//
+/listfun.c/1.1/Fri Apr 20 18:23:20 2001//
+/listfun.h/1.1/Fri Apr 20 18:23:20 2001//
+/nlist.c/1.2/Sat May 12 21:34:42 2001//
+/nlist.h/1.1/Fri Apr 20 18:23:20 2001//
+/process.c/1.4/Thu Jul 31 11:21:50 2003//
+/process.h/1.2/Mon Jun 11 15:25:30 2001//
+/process_dialog.c/1.1/Fri Apr 20 18:23:20 2001//
+D
diff -Nuar cvs-dia/objects/ER/CVS/Entries dia/objects/ER/CVS/Entries
--- cvs-dia/objects/ER/CVS/Entries	2003-08-30 19:00:46.000000000 +0200
+++ dia/objects/ER/CVS/Entries	2003-08-30 19:39:51.000000000 +0200
@@ -5,4 +5,4 @@
 /er.c/1.7/Fri Feb 23 14:52:16 2001//
 /participation.c/1.25/Wed Aug 20 05:52:18 2003//
 /relationship.c/1.35/Wed Aug 20