Index: src/lemon/lemon_writer.h
===================================================================
--- src/lemon/lemon_writer.h	(revision 1411)
+++ src/lemon/lemon_writer.h	(revision 1421)
@@ -32,5 +32,8 @@
 #include <lemon/error.h>
 #include <lemon/invalid.h>
+#include <lemon/graph_utils.h>
 #include <lemon/bits/item_writer.h>
+#include <lemon/utility.h>
+#include <lemon/maps.h>
 
 
@@ -164,6 +167,4 @@
       : Parent(_writer) {}
 
-    // Writers
-
     template <typename _Item>    
     class WriterBase {
@@ -185,5 +186,5 @@
       typedef _Item Item;
       
-      const Map& map;
+      typename SmartConstReference<Map>::Type map;
       Writer writer;
 
@@ -307,6 +308,6 @@
     /// Add a new node map writer command for the writer.
     template <typename Map>
-    NodeSetWriter& writeMap(std::string name, const Map& map) {
-      return writeMap<typename Traits::
+    NodeSetWriter& writeNodeMap(std::string name, const Map& map) {
+      return writeNodeMap<typename Traits::
 	template Writer<typename Map::Value>, Map>(name, map);
     }
@@ -316,6 +317,6 @@
     /// Add a new node map writer command for the writer.
     template <typename Writer, typename Map>
-    NodeSetWriter& writeMap(std::string name, const Map& map, 
-			     const Writer& writer = Writer()) {
+    NodeSetWriter& writeNodeMap(std::string name, const Map& map, 
+			    const Writer& writer = Writer()) {
       writers.push_back(
 	make_pair(name, new MapWriter<Item, Map, Writer>(map, writer)));
@@ -395,5 +396,5 @@
     bool forceIdMap;
    
-    const Graph& graph;   
+    typename SmartConstReference<Graph>::Type graph;   
     std::string id;
 
@@ -401,7 +402,7 @@
 
   /// \ingroup io_group
-  /// \brief SectionWriter for writing a graph's edgeset.
-  ///
-  /// The lemon format can store multiple graph edgesets with several maps.
+  /// \brief SectionWriter for writing a graph's edgesets.
+  ///
+  /// The lemon format can store multiple graph edgesets with several maps. 
   /// The edgeset section's header line is \c \@edgeset \c edgeset_id, but the
   /// \c edgeset_id may be empty.
@@ -414,5 +415,5 @@
   /// If the edgeset contains an \c "id" named map then it will be regarded
   /// as id map. This map should contain only unique values and when the 
-  /// \c writeId() member will be called with a edge it will write it's id.
+  /// \c writeId() member will be called with an edge it will write it's id.
   /// Otherwise if the \c _forceIdMap constructor parameter is true then
   /// the id map will be the id in the graph.
@@ -437,5 +438,5 @@
     /// attach it into the given LemonWriter. It will write node ids by
     /// the \c _nodeIdWriter. If the \c _forceIdMap parameter is true 
-    /// then the writer will write own id map when the user does not give 
+    /// then the writer will write own id map if the user does not give 
     /// "id" named map.
     template <typename NodeIdWriter>
@@ -465,19 +466,19 @@
   public:
 
-    /// \brief Add a new node map writer command for the writer.
-    ///
-    /// Add a new node map writer command for the writer.
+    /// \brief Add a new edge map writer command for the writer.
+    ///
+    /// Add a new edge map writer command for the writer.
     template <typename Map>
-    EdgeSetWriter& writeMap(std::string name, const Map& map) {
-      return writeMap<typename Traits::
+    EdgeSetWriter& writeEdgeMap(std::string name, const Map& map) {
+      return writeEdgeMap<typename Traits::
 	template Writer<typename Map::Value>, Map>(name, map);
     }
 
-    /// \brief Add a new node map writer command for the writer.
-    ///
-    /// Add a new node map writer command for the writer.
+    /// \brief Add a new edge map writer command for the writer.
+    ///
+    /// Add a new edge map writer command for the writer.
     template <typename Writer, typename Map>
-    EdgeSetWriter& writeMap(std::string name, const Map& map, 
-			     const Writer& writer = Writer()) {
+    EdgeSetWriter& writeEdgeMap(std::string name, const Map& map, 
+			    const Writer& writer = Writer()) {
       writers.push_back(
 	make_pair(name, new MapWriter<Item, Map, Writer>(map, writer)));
@@ -562,5 +563,201 @@
     bool forceIdMap;
    
-    const Graph& graph;   
+    typename SmartConstReference<Graph>::Type graph;   
+    std::string id;
+
+    std::auto_ptr<IdWriterBase<typename Graph::Node> > nodeIdWriter;
+  };
+
+  /// \ingroup io_group
+  /// \brief SectionWriter for writing a undirected edgeset.
+  ///
+  /// The lemon format can store multiple undirected edgesets with several 
+  /// maps. The undirected edgeset section's header line is \c \@undiredgeset 
+  /// \c undiredgeset_id, but the \c undiredgeset_id may be empty.
+  ///
+  /// The first line of the section contains the names of the maps separated
+  /// with white spaces. Each next lines describes an undirected edge in the 
+  /// edgeset. The line contains the two connected nodes' id and the mapped 
+  /// values for each undirected map.
+  ///
+  /// The section can handle the directed as a syntactical sugar. Two
+  /// undirected edge map describes one directed edge map. This two maps
+  /// are the forward map and the backward map and the names of this map
+  /// is near the same just with a prefix \c '+' or \c '-' character 
+  /// difference.
+  ///
+  /// If the edgeset contains an \c "id" named map then it will be regarded
+  /// as id map. This map should contain only unique values and when the 
+  /// \c writeId() member will be called with an undirected edge it will 
+  /// write it's id. Otherwise if the \c _forceIdMap constructor parameter
+  /// is true then the id map will be the id in the graph.
+  ///
+  /// The undirected edgeset writer needs a node id writer to identify 
+  /// which nodes have to be connected. If a NodeSetWriter can write the 
+  /// nodes' id, it will be able to use with this class.
+  ///
+  /// \relates LemonWriter
+  template <typename _Graph, typename _Traits = DefaultWriterTraits>
+  class UndirEdgeSetWriter : public CommonSectionWriterBase {
+    typedef CommonSectionWriterBase Parent;
+  public:
+
+    typedef _Graph Graph;
+    typedef _Traits Traits;
+    typedef typename Graph::UndirEdge Item;
+
+    /// \brief Constructor.
+    ///
+    /// Constructor for UndirEdgeSetWriter. It creates the UndirEdgeSetWriter
+    /// and attach it into the given LemonWriter. It will write node ids by
+    /// the \c _nodeIdWriter. If the \c _forceIdMap parameter is true 
+    /// then the writer will write own id map if the user does not give 
+    /// "id" named map.
+    template <typename NodeIdWriter>
+    UndirEdgeSetWriter(LemonWriter& _writer, const Graph& _graph, 
+		       const NodeIdWriter& _nodeIdWriter, 
+		       const std::string& _id = std::string(),
+		       bool _forceIdMap = true)
+      : Parent(_writer), idMap(0), forceIdMap(_forceIdMap),
+	graph(_graph), id(_id),
+	nodeIdWriter(new IdWriter<typename Graph::Node, NodeIdWriter>
+		     (_nodeIdWriter)) {} 
+
+    /// \brief Destructor.
+    ///
+    /// Destructor for UndirEdgeSetWriter.
+    virtual ~UndirEdgeSetWriter() {
+      typename MapWriters::iterator it;
+      for (it = writers.begin(); it != writers.end(); ++it) {
+	delete it->second;
+      }
+    }
+
+  private:
+    UndirEdgeSetWriter(const UndirEdgeSetWriter&);
+    void operator=(const UndirEdgeSetWriter&);
+
+  public:
+
+    /// \brief Add a new undirected edge map writer command for the writer.
+    ///
+    /// Add a new undirected map writer command for the writer.
+    template <typename Map>
+    UndirEdgeSetWriter& writeUndirEdgeMap(std::string name, const Map& map) {
+      return writeUndirEdgeMap<typename Traits::
+	template Writer<typename Map::Value>, Map>(name, map);
+    }
+
+    /// \brief Add a new undirected map writer command for the writer.
+    ///
+    /// Add a new undirected map writer command for the writer.
+    template <typename Writer, typename Map>
+    UndirEdgeSetWriter& writeUndirEdgeMap(std::string name, const Map& map, 
+					  const Writer& writer = Writer()) {
+      writers.push_back(
+	make_pair(name, new MapWriter<Item, Map, Writer>(map, writer)));
+      return *this;
+    }
+
+    /// \brief Add a new directed edge map writer command for the writer.
+    ///
+    /// Add a new directed map writer command for the writer.
+    template <typename Map>
+    UndirEdgeSetWriter& writeEdgeMap(std::string name, const Map& map) {
+      writeUndirEdgeMap("+" + name, composeMap(forwardMap(graph), map));
+      writeUndirEdgeMap("-" + name, composeMap(backwardMap(graph), map));
+      return *this;
+    }
+
+    /// \brief Add a new directed map writer command for the writer.
+    ///
+    /// Add a new directed map writer command for the writer.
+    template <typename Writer, typename Map>
+    UndirEdgeSetWriter& writeEdgeMap(std::string name, const Map& map, 
+				     const Writer& writer = Writer()) {
+      writeUndirEdge("+" + name, composeMap(forwardMap(graph), map), writer);
+      writeUndirEdge("-" + name, composeMap(forwardMap(graph), map), writer);
+      return *this;
+    }
+
+  protected:
+
+    /// \brief The header of the section.
+    ///
+    /// It gives back the header of the section.
+    virtual std::string header() {
+      return "@undiredgeset " + id;
+    }
+
+    /// \brief  Writer function of the section.
+    ///
+    /// Write the content of the section.
+    virtual void write(std::ostream& os) {
+      for (int i = 0; i < (int)writers.size(); ++i) {
+	if (writers[i].first == "id") {
+	  idMap = writers[i].second;
+	  forceIdMap = false;
+	  break;
+	}
+      }
+      os << "\t\t";
+      if (forceIdMap) {
+	os << "id\t";
+      }
+      for (int i = 0; i < (int)writers.size(); ++i) {
+	os << writers[i].first << '\t';
+      }
+      os << std::endl;
+      for (typename Graph::UndirEdgeIt it(graph); it != INVALID; ++it) {
+	nodeIdWriter->write(os, graph.source(it));
+	os << '\t';
+	nodeIdWriter->write(os, graph.target(it));
+	os << '\t';
+	if (forceIdMap) {
+	  os << graph.id(it) << '\t';
+	}
+	for (int i = 0; i < (int)writers.size(); ++i) {
+	  writers[i].second->write(os, it);
+	  os << '\t';
+	}
+	os << std::endl;
+      }
+    }
+
+  public:
+
+    /// \brief Returns true if the undirected edgeset can write the ids of 
+    /// the edges.
+    ///
+    /// Returns true if the undirected edgeset can write the ids of the 
+    /// undirected edges. It is possible only if an "id" named map was 
+    /// written or the \c _forceIdMap constructor parameter was true.
+    bool isIdWriter() const {
+      return forceIdMap || idMap != 0;
+    }
+
+    /// \brief Write the id of the given undirected edge.
+    ///
+    /// It writes the id of the given undirected edge. If there was written 
+    /// an "id" named map then it will write the map value belongs to the 
+    /// undirected edge. Otherwise if the \c forceId parameter was true it 
+    /// will write its id in the graph. 
+    void writeId(std::ostream& os, const Item& item) const {
+      if (forceIdMap) {
+	os << graph.id(item);
+      } else {
+	idMap->write(os, item);
+      }
+    } 
+
+  private:
+
+    typedef std::vector<std::pair<std::string, WriterBase<Item>*> > MapWriters;
+    MapWriters writers;
+
+    WriterBase<Item>* idMap;
+    bool forceIdMap;
+   
+    typename SmartConstReference<Graph>::Type graph;   
     std::string id;
 
@@ -618,5 +815,5 @@
     /// \brief Header checking function.
     ///
-    /// It gives back true when the header line start with \c @nodes,
+    /// It gives back true when the header line start with \c \@nodes,
     /// and the header line's id and the writer's id are the same.
     virtual std::string header() {
@@ -645,5 +842,5 @@
 
   /// \ingroup io_group
-  /// \brief SectionWriter for writeing labeled edges.
+  /// \brief SectionWriter for writing labeled edges.
   ///
   /// The edges section's header line is \c \@edges \c edges_id, but the
@@ -682,7 +879,7 @@
   public:
 
-    /// \brief Add an edge writer command for the NodeWriter.
-    ///
-    /// Add an edge writer command for the NodeWriter.
+    /// \brief Add an edge writer command for the EdgeWriter.
+    ///
+    /// Add an edge writer command for the EdgeWriter.
     void writeEdge(const std::string& name, const Item& item) {
       writers.push_back(make_pair(name, &item));
@@ -693,5 +890,83 @@
     /// \brief Header checking function.
     ///
-    /// It gives back true when the header line start with \c @nodes,
+    /// It gives back true when the header line start with \c \@edges,
+    /// and the header line's id and the writer's id are the same.
+    virtual std::string header() {
+      return "@edges " + id;
+    }
+
+    /// \brief  Writer function of the section.
+    ///
+    /// Write the content of the section.
+    virtual void write(std::ostream& os) {
+      for (int i = 0; i < (int)writers.size(); ++i) {
+	os << writers[i].first << ' ';
+	idWriter->write(os, *(writers[i].second));
+	os << std::endl;
+      }
+    }
+    
+  private:
+
+    std::string id;
+
+    typedef std::vector<std::pair<std::string, const Item*> > ItemWriters;
+    ItemWriters writers;
+
+    std::auto_ptr<IdWriterBase<Item> > idWriter;
+  };
+
+  /// \ingroup io_group
+  /// \brief SectionWriter for writing labeled undirected edges.
+  ///
+  /// The undirected edges section's header line is \c \@undiredges 
+  /// \c undiredges_id, but the \c undiredges_id may be empty.
+  ///
+  /// Each line in the section contains the label of the undirected edge and 
+  /// then the undirected edge id. 
+  ///
+  /// \relates LemonWriter
+  template <typename _Graph>
+  class UndirEdgeWriter : public CommonSectionWriterBase {
+    typedef CommonSectionWriterBase Parent;
+    typedef _Graph Graph;
+    typedef typename Graph::UndirEdge Item;
+  public:
+    
+    /// \brief Constructor.
+    ///
+    /// Constructor for UndirEdgeWriter. It creates the UndirEdgeWriter and
+    /// attach it into the given LemonWriter. The given \c _IdWriter
+    /// will write the undirected edges' id what can be an undirected 
+    /// edgeset writer.
+    template <typename _IdWriter>
+    UndirEdgeWriter(LemonWriter& _writer, const _IdWriter& _idWriter, 
+	       const std::string& _id = std::string()) 
+      : Parent(_writer), id(_id), 
+	idWriter(new IdWriter<typename Graph::UndirEdge, _IdWriter>
+		 (_idWriter)) {} 
+
+    /// \brief Destructor.
+    ///
+    /// Destructor for UndirEdgeWriter.
+    virtual ~UndirEdgeWriter() {}
+  private:
+    UndirEdgeWriter(const UndirEdgeWriter&);
+    void operator=(const UndirEdgeWriter&);
+
+  public:
+
+    /// \brief Add an undirected edge writer command for the UndirEdgeWriter.
+    ///
+    /// Add an edge writer command for the UndirEdgeWriter.
+    void writeUndirEdge(const std::string& name, const Item& item) {
+      writers.push_back(make_pair(name, &item));
+    }
+
+  protected:
+
+    /// \brief Header checking function.
+    ///
+    /// It gives back true when the header line start with \c \@undiredges,
     /// and the header line's id and the writer's id are the same.
     virtual std::string header() {
