1 /* Dia -- an diagram creation/manipulation program
2 * Copyright (C) 1998 Alexander Larsson
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 #include <sys/types.h>
34 #include <libxml/tree.h>
35 #include <libxml/parser.h>
36 #include <libxml/xmlmemory.h>
37 #include "dia_xml_libxml.h"
40 #include "load_save.h"
42 #include "diagramdata.h"
44 #include "preferences.h"
45 #include "diapagelayout.h"
50 #define mkstemp(s) _open(_mktemp(s), O_CREAT | O_TRUNC | O_WRONLY | _O_BINARY, 0644)
51 #define fchmod(f,m) (0)
54 #define mkstemp(s) _open(_mktemp(s), O_CREAT | O_TRUNC | O_WRONLY | O_BINARY, 0644)
55 #define fchmod(f,m) (0)
59 GHFuncUnknownObjects(gpointer key
,
63 GString
* s
= (GString
*)user_data
;
64 g_string_append(s
, "\n");
65 g_string_append(s
, (gchar
*)key
);
70 read_objects(xmlNodePtr objects
, Layer
*layer
,
71 GHashTable
*objects_hash
,const char *filename
, Object
*parent
)
81 GHashTable
* unknown_hash
;
83 xmlNodePtr child_node
;
85 unknown_hash
= g_hash_table_new(g_str_hash
, g_str_equal
);
86 unknown_str
= g_string_new("Unknown types while reading diagram file");
90 obj_node
= objects
->xmlChildrenNode
;
92 while ( obj_node
!= NULL
) {
93 if (xmlIsBlankNode(obj_node
)) {
94 obj_node
= obj_node
->next
;
100 if (strcmp(obj_node
->name
, "object")==0) {
101 typestr
= xmlGetProp(obj_node
, "type");
102 versionstr
= xmlGetProp(obj_node
, "version");
103 id
= xmlGetProp(obj_node
, "id");
106 if (versionstr
!= NULL
) {
107 version
= atoi(versionstr
);
111 type
= object_get_type((char *)typestr
);
114 if (NULL
== g_hash_table_lookup(unknown_hash
, typestr
))
115 g_hash_table_insert(unknown_hash
, g_strdup(typestr
), 0);
119 obj
= type
->ops
->load(obj_node
, version
, filename
);
120 layer_add_object(layer
,obj
);
121 list
= g_list_append(list
, obj
);
125 obj
->parent
= parent
;
126 parent
->children
= g_list_append(parent
->children
, obj
);
129 g_hash_table_insert(objects_hash
, g_strdup((char *)id
), obj
);
131 child_node
= obj_node
->children
;
135 if (strcmp(child_node
->name
, "children") == 0)
137 list
= g_list_concat(list
, read_objects(child_node
, layer
, objects_hash
, filename
, obj
));
140 child_node
= child_node
->next
;
143 if (typestr
) xmlFree(typestr
);
144 if (id
) xmlFree (id
);
145 } else if (strcmp(obj_node
->name
, "group")==0) {
146 obj
= group_create(read_objects(obj_node
, layer
,
147 objects_hash
, filename
, NULL
));
148 layer_add_object(layer
,obj
);
150 list
= g_list_append(list
, obj
);
152 /* silently ignore other nodes */
155 obj_node
= obj_node
->next
;
157 /* show all the unknown types in one message */
158 if (0 < g_hash_table_size(unknown_hash
)) {
159 g_hash_table_foreach(unknown_hash
,
160 GHFuncUnknownObjects
,
162 message_error(unknown_str
->str
);
164 g_hash_table_destroy(unknown_hash
);
165 g_string_free(unknown_str
, TRUE
);
171 read_connections(GList
*objects
, xmlNodePtr layer_node
,
172 GHashTable
*objects_hash
)
176 xmlNodePtr connections
;
177 xmlNodePtr connection
;
185 obj_node
= layer_node
->xmlChildrenNode
;
186 while ((list
!= NULL
) && (obj_node
!= NULL
)) {
187 Object
*obj
= (Object
*) list
->data
;
189 while (obj_node
&& xmlIsBlankNode(obj_node
)) obj_node
= obj_node
->next
;
190 if (!obj_node
) break;
193 read_connections(group_objects(obj
), obj_node
, objects_hash
);
195 connections
= obj_node
->xmlChildrenNode
;
196 while ((connections
!=NULL
) &&
197 (strcmp(connections
->name
, "connections")!=0))
198 connections
= connections
->next
;
199 if (connections
!= NULL
) {
200 connection
= connections
->xmlChildrenNode
;
201 while (connection
!= NULL
) {
202 if (xmlIsBlankNode(connection
)) {
203 connection
= connection
->next
;
206 handlestr
= xmlGetProp(connection
, "handle");
207 tostr
= xmlGetProp(connection
, "to");
208 connstr
= xmlGetProp(connection
, "connection");
210 handle
= atoi(handlestr
);
211 conn
= atoi(connstr
);
213 to
= g_hash_table_lookup(objects_hash
, tostr
);
215 if (handlestr
) xmlFree(handlestr
);
216 if (connstr
) xmlFree(connstr
);
217 if (tostr
) xmlFree(tostr
);
220 message_error(_("Error loading diagram.\n"
221 "Linked object not found in document."));
222 } else if (conn
>= 0 && conn
>= to
->num_connections
) {
223 message_error(_("Error loading diagram.\n"
224 "connection point does not exist."));
225 } else if (handle
>= 0 && handle
>= obj
->num_handles
) {
226 message_error(_("Error loading diagram.\n"
227 "connection handle does not exist."));
229 object_connect(obj
, obj
->handles
[handle
],
230 to
->connections
[conn
]);
233 connection
= connection
->next
;
239 list
= g_list_next(list
);
240 obj_node
= obj_node
->next
;
245 hash_free_string(gpointer key
,
253 find_node_named (xmlNodePtr p
, const char *name
)
255 while (p
&& 0 != strcmp(p
->name
, name
))
261 diagram_data_load(const char *filename
, DiagramData
*data
, void* user_data
)
263 GHashTable
*objects_hash
;
267 xmlNodePtr diagramdata
;
268 xmlNodePtr paperinfo
, gridinfo
, guideinfo
;
269 xmlNodePtr layer_node
;
275 if (g_file_test (filename
, G_FILE_TEST_IS_DIR
)) {
276 message_error(_("You must specify a file, not a directory.\n"));
280 fd
= open(filename
, O_RDONLY
);
283 message_error(_("Couldn't open: '%s' for reading.\n"), filename
);
287 if (read(fd
, &firstchar
, 1)) {
288 data
->is_compressed
= (firstchar
!= '<');
290 /* Couldn't read a single char? Set to default. */
291 data
->is_compressed
= prefs
.new_diagram
.compress_save
;
294 /* Note that this closing and opening means we can't read from a pipe */
297 doc
= xmlDiaParseFile(filename
);
300 message_error(_("Error loading diagram %s.\nUnknown file type."),filename
);
304 if (doc
->xmlRootNode
== NULL
) {
305 message_error(_("Error loading diagram %s.\nUnknown file type."),filename
);
310 namespace = xmlSearchNs(doc
, doc
->xmlRootNode
, "dia");
311 if (strcmp (doc
->xmlRootNode
->name
, "diagram") || (namespace == NULL
)){
312 message_error(_("Error loading diagram %s.\nNot a Dia file."), filename
);
317 /* Destroy the default layer: */
318 g_ptr_array_remove(data
->layers
, data
->active_layer
);
319 layer_destroy(data
->active_layer
);
322 find_node_named (doc
->xmlRootNode
->xmlChildrenNode
, "diagramdata");
324 /* Read in diagram data: */
325 data
->bg_color
= prefs
.new_diagram
.bg_color
;
326 attr
= composite_find_attribute(diagramdata
, "background");
328 data_color(attribute_first_data(attr
), &data
->bg_color
);
330 data
->pagebreak_color
= prefs
.new_diagram
.pagebreak_color
;
331 attr
= composite_find_attribute(diagramdata
, "pagebreak");
333 data_color(attribute_first_data(attr
), &data
->pagebreak_color
);
335 /* load paper information from diagramdata section */
336 attr
= composite_find_attribute(diagramdata
, "paper");
338 paperinfo
= attribute_first_data(attr
);
340 attr
= composite_find_attribute(paperinfo
, "name");
342 g_free(data
->paper
.name
);
343 data
->paper
.name
= data_string(attribute_first_data(attr
));
345 /* set default margins for paper size ... */
346 dia_page_layout_get_default_margins(data
->paper
.name
,
347 &data
->paper
.tmargin
,
348 &data
->paper
.bmargin
,
349 &data
->paper
.lmargin
,
350 &data
->paper
.rmargin
);
352 attr
= composite_find_attribute(paperinfo
, "tmargin");
354 data
->paper
.tmargin
= data_real(attribute_first_data(attr
));
355 attr
= composite_find_attribute(paperinfo
, "bmargin");
357 data
->paper
.bmargin
= data_real(attribute_first_data(attr
));
358 attr
= composite_find_attribute(paperinfo
, "lmargin");
360 data
->paper
.lmargin
= data_real(attribute_first_data(attr
));
361 attr
= composite_find_attribute(paperinfo
, "rmargin");
363 data
->paper
.rmargin
= data_real(attribute_first_data(attr
));
365 attr
= composite_find_attribute(paperinfo
, "is_portrait");
366 data
->paper
.is_portrait
= TRUE
;
368 data
->paper
.is_portrait
= data_boolean(attribute_first_data(attr
));
370 attr
= composite_find_attribute(paperinfo
, "scaling");
371 data
->paper
.scaling
= 1.0;
373 data
->paper
.scaling
= data_real(attribute_first_data(attr
));
375 attr
= composite_find_attribute(paperinfo
, "fitto");
376 data
->paper
.fitto
= FALSE
;
378 data
->paper
.fitto
= data_boolean(attribute_first_data(attr
));
380 attr
= composite_find_attribute(paperinfo
, "fitwidth");
381 data
->paper
.fitwidth
= 1;
383 data
->paper
.fitwidth
= data_int(attribute_first_data(attr
));
385 attr
= composite_find_attribute(paperinfo
, "fitheight");
386 data
->paper
.fitheight
= 1;
388 data
->paper
.fitheight
= data_int(attribute_first_data(attr
));
390 /* calculate effective width/height */
391 dia_page_layout_get_paper_size(data
->paper
.name
,
393 &data
->paper
.height
);
394 if (!data
->paper
.is_portrait
) {
395 gfloat tmp
= data
->paper
.width
;
397 data
->paper
.width
= data
->paper
.height
;
398 data
->paper
.height
= tmp
;
400 data
->paper
.width
-= data
->paper
.lmargin
;
401 data
->paper
.width
-= data
->paper
.rmargin
;
402 data
->paper
.height
-= data
->paper
.tmargin
;
403 data
->paper
.height
-= data
->paper
.bmargin
;
404 data
->paper
.width
/= data
->paper
.scaling
;
405 data
->paper
.height
/= data
->paper
.scaling
;
407 attr
= composite_find_attribute(diagramdata
, "grid");
409 gridinfo
= attribute_first_data(attr
);
411 attr
= composite_find_attribute(gridinfo
, "width_x");
413 data
->grid
.width_x
= data_real(attribute_first_data(attr
));
414 attr
= composite_find_attribute(gridinfo
, "width_y");
416 data
->grid
.width_y
= data_real(attribute_first_data(attr
));
417 attr
= composite_find_attribute(gridinfo
, "visible_x");
419 data
->grid
.visible_x
= data_int(attribute_first_data(attr
));
420 attr
= composite_find_attribute(gridinfo
, "visible_y");
422 data
->grid
.visible_y
= data_int(attribute_first_data(attr
));
424 data
->grid
.colour
= prefs
.new_diagram
.grid_color
;
425 attr
= composite_find_attribute(diagramdata
, "color");
427 data_color(attribute_first_data(attr
), &data
->grid
.colour
);
430 attr
= composite_find_attribute(diagramdata
, "guides");
435 guideinfo
= attribute_first_data(attr
);
437 attr
= composite_find_attribute(guideinfo
, "hguides");
439 data
->guides
.nhguides
= attribute_num_data(attr
);
440 g_free(data
->guides
.hguides
);
441 data
->guides
.hguides
= g_new(real
, data
->guides
.nhguides
);
443 guide
= attribute_first_data(attr
);
444 for (i
= 0; i
< data
->guides
.nhguides
; i
++, guide
= data_next(guide
))
445 data
->guides
.hguides
[i
] = data_real(guide
);
447 attr
= composite_find_attribute(guideinfo
, "vguides");
449 data
->guides
.nvguides
= attribute_num_data(attr
);
450 g_free(data
->guides
.vguides
);
451 data
->guides
.vguides
= g_new(real
, data
->guides
.nvguides
);
453 guide
= attribute_first_data(attr
);
454 for (i
= 0; i
< data
->guides
.nvguides
; i
++, guide
= data_next(guide
))
455 data
->guides
.vguides
[i
] = data_real(guide
);
459 /* Read in all layers: */
461 find_node_named (doc
->xmlRootNode
->xmlChildrenNode
, "layer");
463 objects_hash
= g_hash_table_new(g_str_hash
, g_str_equal
);
465 while (layer_node
!= NULL
) {
469 if (xmlIsBlankNode(layer_node
)) {
470 layer_node
= layer_node
->next
;
474 if (!layer_node
) break;
476 name
= (char *)xmlGetProp(layer_node
, "name");
477 if (!name
) break; /* name is mandatory */
479 visible
= (char *)xmlGetProp(layer_node
, "visible");
481 layer
= new_layer(g_strdup(name
), data
);
482 if (name
) xmlFree(name
);
484 layer
->visible
= FALSE
;
485 if ((visible
) && (strcmp(visible
, "true")==0))
486 layer
->visible
= TRUE
;
487 if (visible
) xmlFree(visible
);
489 /* Read in all objects: */
491 list
= read_objects(layer_node
, layer
, objects_hash
, filename
, NULL
);
492 layer
->objects
= list
;
493 read_connections( list
, layer_node
, objects_hash
);
495 data_add_layer(data
, layer
);
497 layer_node
= layer_node
->next
;
500 data
->active_layer
= (Layer
*) g_ptr_array_index(data
->layers
, 0);
504 g_hash_table_foreach(objects_hash
, hash_free_string
, NULL
);
506 g_hash_table_destroy(objects_hash
);
508 if (data
->layers
->len
< 1) {
509 message_error (_("Error loading diagram:\n%s.\n"
510 "A valid Dia file defines at least one layer."),
519 write_objects(GList
*objects
, xmlNodePtr objects_node
,
520 GHashTable
*objects_hash
, int *obj_nr
, const char *filename
)
524 xmlNodePtr group_node
;
525 xmlNodePtr parent_node
;
529 while (list
!= NULL
) {
530 Object
*obj
= (Object
*) list
->data
;
532 if (g_hash_table_lookup(objects_hash
, obj
))
534 list
= g_list_next(list
);
539 group_node
= xmlNewChild(objects_node
, NULL
, "group", NULL
);
540 write_objects(group_objects(obj
), group_node
,
541 objects_hash
, obj_nr
, filename
);
543 obj_node
= xmlNewChild(objects_node
, NULL
, "object", NULL
);
545 xmlSetProp(obj_node
, "type", obj
->type
->name
);
547 g_snprintf(buffer
, 30, "%d", obj
->type
->version
);
548 xmlSetProp(obj_node
, "version", buffer
);
550 g_snprintf(buffer
, 30, "O%d", *obj_nr
);
551 xmlSetProp(obj_node
, "id", buffer
);
553 (*obj
->type
->ops
->save
)(obj
, obj_node
, filename
);
555 /* Add object -> obj_nr to hash table */
556 g_hash_table_insert(objects_hash
, obj
, GINT_TO_POINTER(*obj_nr
));
559 if (obj
->can_parent
&& obj
->children
)
561 parent_node
= xmlNewChild(obj_node
, NULL
, "children", NULL
);
562 write_objects(obj
->children
, parent_node
,
563 objects_hash
, obj_nr
, filename
);
567 list
= g_list_next(list
);
572 write_connections(GList
*objects
, xmlNodePtr layer_node
,
573 GHashTable
*objects_hash
)
577 xmlNodePtr connections
;
578 xmlNodePtr connection
;
583 obj_node
= layer_node
->xmlChildrenNode
;
584 while ((list
!= NULL
) && (obj_node
!= NULL
)) {
585 Object
*obj
= (Object
*) list
->data
;
587 while (obj_node
&& xmlIsBlankNode(obj_node
)) obj_node
= obj_node
->next
;
588 if (!obj_node
) break;
591 write_connections(group_objects(obj
), obj_node
, objects_hash
);
595 for (i
=0;i
<obj
->num_handles
;i
++) {
596 ConnectionPoint
*con_point
;
599 handle
= obj
->handles
[i
];
600 con_point
= handle
->connected_to
;
602 if ( con_point
!= NULL
) {
606 other_obj
= con_point
->object
;
609 while (other_obj
->connections
[con_point_nr
] != con_point
) {
611 if (con_point_nr
>=other_obj
->num_connections
) {
612 message_error("Internal error saving diagram\n con_point_nr >= other_obj->num_connections\n");
617 if (connections
== NULL
)
618 connections
= xmlNewChild(obj_node
, NULL
, "connections", NULL
);
620 connection
= xmlNewChild(connections
, NULL
, "connection", NULL
);
621 /* from what handle on this object*/
622 g_snprintf(buffer
, 30, "%d", i
);
623 xmlSetProp(connection
, "handle", buffer
);
625 g_snprintf(buffer
, 30, "O%d",
626 GPOINTER_TO_INT(g_hash_table_lookup(objects_hash
,
628 xmlSetProp(connection
, "to", buffer
);
629 /* to what connection_point on that object */
630 g_snprintf(buffer
, 30, "%d", con_point_nr
);
631 xmlSetProp(connection
, "connection", buffer
);
636 list
= g_list_next(list
);
637 obj_node
= obj_node
->next
;
642 /* Filename seems to be junk, but is passed on to objects */
644 diagram_data_write_doc(DiagramData
*data
, const char *filename
)
648 xmlNodePtr pageinfo
, gridinfo
, guideinfo
;
649 xmlNodePtr layer_node
;
650 GHashTable
*objects_hash
;
658 doc
= xmlNewDoc("1.0");
659 doc
->encoding
= xmlStrdup("UTF-8");
660 doc
->xmlRootNode
= xmlNewDocNode(doc
, NULL
, "diagram", NULL
);
662 name_space
= xmlNewNs(doc
->xmlRootNode
,
663 "http://www.lysator.liu.se/~alla/dia/",
665 xmlSetNs(doc
->xmlRootNode
, name_space
);
667 tree
= xmlNewChild(doc
->xmlRootNode
, name_space
, "diagramdata", NULL
);
669 attr
= new_attribute((ObjectNode
)tree
, "background");
670 data_add_color(attr
, &data
->bg_color
);
672 attr
= new_attribute((ObjectNode
)tree
, "pagebreak");
673 data_add_color(attr
, &data
->pagebreak_color
);
675 attr
= new_attribute((ObjectNode
)tree
, "paper");
676 pageinfo
= data_add_composite(attr
, "paper");
677 data_add_string(composite_add_attribute(pageinfo
, "name"),
679 data_add_real(composite_add_attribute(pageinfo
, "tmargin"),
680 data
->paper
.tmargin
);
681 data_add_real(composite_add_attribute(pageinfo
, "bmargin"),
682 data
->paper
.bmargin
);
683 data_add_real(composite_add_attribute(pageinfo
, "lmargin"),
684 data
->paper
.lmargin
);
685 data_add_real(composite_add_attribute(pageinfo
, "rmargin"),
686 data
->paper
.rmargin
);
687 data_add_boolean(composite_add_attribute(pageinfo
, "is_portrait"),
688 data
->paper
.is_portrait
);
689 data_add_real(composite_add_attribute(pageinfo
, "scaling"),
690 data
->paper
.scaling
);
691 data_add_boolean(composite_add_attribute(pageinfo
, "fitto"),
693 if (data
->paper
.fitto
) {
694 data_add_int(composite_add_attribute(pageinfo
, "fitwidth"),
695 data
->paper
.fitwidth
);
696 data_add_int(composite_add_attribute(pageinfo
, "fitheight"),
697 data
->paper
.fitheight
);
700 attr
= new_attribute((ObjectNode
)tree
, "grid");
701 gridinfo
= data_add_composite(attr
, "grid");
702 data_add_real(composite_add_attribute(gridinfo
, "width_x"),
704 data_add_real(composite_add_attribute(gridinfo
, "width_y"),
706 data_add_int(composite_add_attribute(gridinfo
, "visible_x"),
707 data
->grid
.visible_x
);
708 data_add_int(composite_add_attribute(gridinfo
, "visible_y"),
709 data
->grid
.visible_y
);
710 attr
= new_attribute((ObjectNode
)tree
, "color");
711 data_add_composite(gridinfo
, "color");
712 data_add_color(attr
, &data
->grid
.colour
);
715 attr
= new_attribute((ObjectNode
)tree
, "guides");
716 guideinfo
= data_add_composite(attr
, "guides");
717 attr
= composite_add_attribute(guideinfo
, "hguides");
718 for (i
= 0; i
< data
->guides
.nhguides
; i
++)
719 data_add_real(attr
, data
->guides
.hguides
[i
]);
720 attr
= composite_add_attribute(guideinfo
, "vguides");
721 for (i
= 0; i
< data
->guides
.nvguides
; i
++)
722 data_add_real(attr
, data
->guides
.vguides
[i
]);
724 objects_hash
= g_hash_table_new(g_direct_hash
, g_direct_equal
);
728 for (i
= 0; i
< data
->layers
->len
; i
++) {
729 layer_node
= xmlNewChild(doc
->xmlRootNode
, name_space
, "layer", NULL
);
730 layer
= (Layer
*) g_ptr_array_index(data
->layers
, i
);
731 xmlSetProp(layer_node
, "name", layer
->name
);
734 xmlSetProp(layer_node
, "visible", "true");
736 xmlSetProp(layer_node
, "visible", "false");
738 write_objects(layer
->objects
, layer_node
,
739 objects_hash
, &obj_nr
, filename
);
741 res
= write_connections(layer
->objects
, layer_node
, objects_hash
);
742 /* Why do we bail out like this? It leaks! */
746 g_hash_table_destroy(objects_hash
);
748 if (data
->is_compressed
)
749 xmlSetDocCompressMode(doc
, 9);
751 xmlSetDocCompressMode(doc
, 0);
756 /** This tries to save the diagram into a file, without any backup
757 * Returns >= 0 on success.
758 * Only for internal use. */
760 diagram_data_raw_save(DiagramData
*data
, const char *filename
)
765 doc
= diagram_data_write_doc(data
, filename
);
767 ret
= xmlDiaSaveFile (filename
, doc
);
773 /** This saves the diagram, using a backup in case of failure */
775 diagram_data_save(DiagramData
*data
, const char *filename
)
778 char *bakname
,*tmpname
,*dirname
,*p
;
783 /* build the temporary and backup file names */
784 dirname
= g_strdup(filename
);
785 p
= strrchr((char *)dirname
,G_DIR_SEPARATOR
);
790 dirname
= g_strdup("." G_DIR_SEPARATOR_S
);
792 tmpname
= g_strconcat(dirname
,"__diaXXXXXX",NULL
);
793 bakname
= g_strconcat(filename
,"~",NULL
);
795 /* open a temporary name, and fix the modes to match what fopen() would have
796 done (mkstemp() is (rightly so) a bit paranoid for what we do). */
797 fildes
= mkstemp(tmpname
);
798 _umask
= umask(0); umask(_umask
);
799 mode
= 0666 & ~_umask
;
800 ret
= fchmod(fildes
,mode
);
801 file
= fdopen(fildes
,"wb");
803 /* Now write the data in the temporary file name. */
806 message_error(_("Can't open output file %s: %s\n"), tmpname
, strerror(errno
));
811 ret
= diagram_data_raw_save(data
, tmpname
);
814 /* Save failed; we clean our stuff up, without touching the file named
815 "filename" if it existed. */
822 /* save succeeded. We kill the old backup file, move the old file into
823 backup, and the temp file into the new saved file. */
825 rename(filename
,bakname
);
826 ret
= rename(tmpname
,filename
);
830 return (ret
?FALSE
:TRUE
);
834 diagram_save(Diagram
*dia
, const char *filename
)
836 gboolean res
= diagram_data_save(dia
->data
, filename
);
839 message_error(_("Failed to save file '%s'.\n"), filename
);
843 dia
->unsaved
= FALSE
;
844 diagram_set_modified (dia
, FALSE
);
846 diagram_cleanup_autosave(dia
);
851 /* Autosave stuff. Needs to use low-level save to avoid setting and resetting flags */
853 diagram_cleanup_autosave(Diagram
*dia
)
858 savefile
= dia
->autosavefilename
;
860 if (savefile
== NULL
) return;
862 if (stat(savefile
, &statbuf
) == 0) { /* Success */
866 dia
->autosavefilename
= NULL
;
867 dia
->autosaved
= FALSE
;
870 /** Absolutely autosave a diagram.
871 * Called after a periodic check at the first idleness.
874 diagram_autosave(Diagram
*dia
)
876 gchar
*save_filename
;
878 /* Must check if the diagram is still valid, or Death Ensues! */
879 GList
*diagrams
= dia_open_diagrams();
881 while (diagrams
!= NULL
) {
882 diagram
= (Diagram
*)diagrams
->data
;
883 if (diagram
== dia
&&
885 !diagram
->autosaved
) {
886 save_filename
= g_strdup_printf("%s.autosave", dia
->filename
);
888 if (dia
->autosavefilename
!= NULL
)
889 g_free(dia
->autosavefilename
);
890 dia
->autosavefilename
= save_filename
;
891 diagram_data_raw_save(dia
->data
, save_filename
);
892 dia
->autosaved
= TRUE
;
895 diagrams
= g_list_next(diagrams
);
899 /* --- filter interfaces --- */
901 export_native(DiagramData
*data
, const gchar
*filename
,
902 const gchar
*diafilename
, void* user_data
)
904 diagram_data_save(data
, filename
);
907 static const gchar
*extensions
[] = { "dia", NULL
};
908 DiaExportFilter dia_export_filter
= {
909 N_("Native Dia Diagram"),
913 DiaImportFilter dia_import_filter
= {
914 N_("Native Dia Diagram"),