# HG changeset patch
# User insilmaril
# Date 1126554771 0
# Node ID 30b22f7bd009c3acaa761de1f47c40f67e32b590
# Parent  2cf3413b6ac9a4b4c4fe17f007f55d4235234cb5
1.7.5 Multiple undos, LaTeX Export (experimental)

diff -r 2cf3413b6ac9 -r 30b22f7bd009 demos/todo.vym
Binary file demos/todo.vym has changed
diff -r 2cf3413b6ac9 -r 30b22f7bd009 exports.cpp
--- a/exports.cpp	Tue Sep 06 15:04:50 2005 +0000
+++ b/exports.cpp	Mon Sep 12 19:52:51 2005 +0000
@@ -21,6 +21,23 @@
 	mapCenter=mc;
 }
 
+QString Export::getSectionString(BranchObj *bostart)
+{
+	QString r;
+	BranchObj *bo=bostart;
+	int depth=bo->getDepth();
+	while (depth>0)
+	{
+		r=QString("%1").arg(1+bo->getNum(),0,10)+"." + r;
+		bo=(BranchObj*)(bo->getParObj());
+		depth=bo->getDepth();
+	}	
+	if (r.isEmpty())
+		return r;
+	else	
+		return r + " ";
+}
+
 void Export::exportMap()
 {
 	QFile file (filepath);
@@ -72,20 +89,129 @@
 	file.close();
 }
 
-QString Export::getSectionString(BranchObj *bostart)
+// Exports a map to a LaTex file.  This file needs to be included or inported into a LaTex document
+// it will not add a preamble, or anything that makes a full LaTex document.
+void Export::exportLaTeX() 
 {
-	QString r;
-	BranchObj *bo=bostart;
-	int depth=bo->getDepth();
-	while (depth>0)
-	{
-		r=QString("%1").arg(1+bo->getNum(),0,10)+"." + r;
-		bo=(BranchObj*)(bo->getParObj());
-		depth=bo->getDepth();
-	}	
-	if (r.isEmpty())
-		return r;
-	else	
-		return r + " ";
+  QFile file (filepath);
+  if ( !file.open( IO_WriteOnly ) ) {
+    // FIXME
+    cout << "Export::exportMap  couldn't open "<<filepath<<endl;
+    return;
+  }
+  QTextStream ts( &file );	// use LANG decoding here...
+  ts.setEncoding (QTextStream::UnicodeUTF8); // Force UTF8
+  
+  // Main loop over all branches
+  QString s;
+  // QString actIndent("");
+  // int i;
+  BranchObj *bo;
+  bo=mapCenter->first();
+  while (bo) {
+    if (bo->getDepth()==0);
+    else if (bo->getDepth()==1) {
+      ts << ("\\chapter{" + bo->getHeading()+ "}\n");
+    }
+    else if (bo->getDepth()==2) {
+      ts << ("\\section{" + bo->getHeading()+ "}\n");
+    }
+    else if (bo->getDepth()==3) {
+      ts << ("\\subsection{" + bo->getHeading()+ "}\n");
+    }
+    else if (bo->getDepth()==4) {
+      ts << ("\\subsubsection{" + bo->getHeading()+ "}\n");
+    }
+    else {
+      ts << ("\\paragraph*{" + bo->getHeading()+ "}\n");
+    }
+    
+    // If necessary, write note
+    if (!bo->getNote().isEmpty()) {
+      ts << (textConvertToASCII(bo->getNote()));
+      ts << ("\n");
+    }
+    
+    bo=bo->next();
+   }
+  file.close();
 }
 
+#include "settings.h"
+
+void Export::exportOOPresentation()
+{
+	QString templateDir="oo-test/suse-template/";
+	QString templateContent="content.xml";
+	QString tmpDir="/tmp/vym-ootest/";
+	QString header="";
+
+
+	// Create tmpdir
+		// TODO
+
+	// Copy template to tmpdir
+		// TODO
+
+
+	// Read content-template
+		// TODO
+	QString content;
+	if (!loadStringFromDisk (templateDir+templateContent,content))
+	{
+		qWarning ("Export::exportOOPresentation() Couldn't load from "+templateDir+templateContent);
+		return;
+	}
+
+
+	// Walk through map
+	QString s;
+	QString actIndent("");
+	uint j;
+	int i;
+	BranchObj *bo;
+	bo=mapCenter->first();
+	while (bo) 
+	{
+		// Make indentstring
+		for (i=0;i<bo->getDepth();i++) actIndent+= indentPerDepth;
+
+		// Write heading
+		//	write (actIndent + getSectionString(bo) + bo->getHeading()+ "\n");
+		if (bo->getDepth()==0)
+		{
+			s+= (bo->getHeading()+ "\n");
+			for (j=0;j<bo->getHeading().length();j++) s+="=";
+			s+= "\n";
+		} else 	if (bo->getDepth()==1)
+			s+= ("\n"+getSectionString(bo) + bo->getHeading()+ "\n");
+		else	if (bo->getDepth()==2)
+			s+= (actIndent + " o " + bo->getHeading()+ "\n");
+		else	
+			s+ (actIndent + " - " + bo->getHeading()+ "\n");
+		
+		/*
+		// If necessary, write note
+		if (!bo->getNote().isEmpty())
+		{
+			s =textConvertToASCII(bo->getNote());
+			s=s.replace ("\n","\n"+actIndent);
+			ts << (s+"\n\n");
+		}
+		*/
+		bo=bo->next();
+		actIndent="";
+	}
+
+	
+	// Insert new content
+		// TODO
+	cout <<"\n\ns="<<s<<endl;
+	content.replace ("<!--INSERT PAGES HERE-->",s);
+	cout << "ExportOO: content=\n"<<content<<endl;
+
+	// zip tmpdir to destination
+		// TODO
+
+}
+
diff -r 2cf3413b6ac9 -r 30b22f7bd009 exports.h
--- a/exports.h	Tue Sep 06 15:04:50 2005 +0000
+++ b/exports.h	Mon Sep 12 19:52:51 2005 +0000
@@ -17,9 +17,12 @@
 	void setPath(const QString &);
 	void setMapCenter (MapCenterObj*);
 	void setIndentPerDepth (QString);
-	void exportMap();
 protected:  
 	QString getSectionString (BranchObj*);
+public:	
+	void exportMap();
+	void exportLaTeX();
+	void exportOOPresentation();
 
 private:
 	QDir outdir;
diff -r 2cf3413b6ac9 -r 30b22f7bd009 main.cpp
--- a/main.cpp	Tue Sep 06 15:04:50 2005 +0000
+++ b/main.cpp	Mon Sep 12 19:52:51 2005 +0000
@@ -33,6 +33,7 @@
 QAction *actionFileSave;
 QAction *actionFilePrint;
 QAction *actionEditUndo;
+QAction *actionEditRedo;
 QAction *actionEditCopy;
 QAction *actionEditCut;
 QAction *actionEditPaste;
diff -r 2cf3413b6ac9 -r 30b22f7bd009 mainwindow.cpp
--- a/mainwindow.cpp	Tue Sep 06 15:04:50 2005 +0000
+++ b/mainwindow.cpp	Mon Sep 12 19:52:51 2005 +0000
@@ -27,7 +27,7 @@
 #include "icons/filesave.xpm"
 #include "icons/fileprint.xpm"
 #include "icons/editundo.xpm"
-//#include "icons/editredo.xpm"	// TODO
+#include "icons/editredo.xpm"	
 #include "icons/editcopy.xpm"
 #include "icons/editcut.xpm"
 #include "icons/editpaste.xpm"
@@ -69,6 +69,7 @@
 extern QAction* actionFileSave;
 extern QAction* actionFilePrint;
 extern QAction* actionEditUndo;
+extern QAction* actionEditRedo;
 extern QAction *actionEditCopy;
 extern QAction *actionEditCut;
 extern QAction *actionEditPaste;
@@ -387,12 +388,15 @@
     a->addTo( tb );
     a->addTo( menu );
 	actionEditUndo=a;
-    /*
-    a = new QAction( tr( "Redo" ), QPixmap( editredo_xpm ), tr( "&Redo" ), CTRL + Key_Y, this, "editRedo" ); 
-    connect( a, SIGNAL( activated() ), this, SLOT( editRedo() ) );
-    a->addTo( tb );
-    a->addTo( menu );
-    */
+    
+    if (settings.readBoolEntry( "/vym/mainwindow/showTestMenu",false)) 
+	{
+		a = new QAction( tr( "Redo" ), QPixmap( editredo_xpm ), tr( "&Redo" ), CTRL + Key_Y, this, "editRedo" ); 
+		connect( a, SIGNAL( activated() ), this, SLOT( editRedo() ) );
+		a->addTo( tb );
+		a->addTo( menu );
+	}
+   
     menu->insertSeparator();
     a = new QAction( tr( "Copy" ), QPixmap( editcopy_xpm ), tr( "&Copy" ), CTRL + Key_C, this, "editCopy" );
     connect( a, SIGNAL( activated() ), this, SLOT( editCopy() ) );
@@ -972,13 +976,24 @@
     connect( a, SIGNAL( activated() ), this, SLOT( fileExportASCII() ) );
 	a->addTo( exportMenu );
 
-	a = new QAction( tr( "Export XML" ), QPixmap(), tr( "Export XML" ),  0, this, "exportXML"+QString("...") );
+    a = new QAction( tr( "Export as LaTeX (still experimental)" ), QPixmap(), tr( "Export (LaTeX)" +QString("...")), 0, this, "exportLaTeX" );
+    connect( a, SIGNAL( activated() ), this, SLOT( fileExportLaTeX() ) );
+	a->addTo( exportMenu );
+
+    if (settings.readBoolEntry( "/vym/mainwindow/showTestMenu",false)) 
+	{
+		a = new QAction( tr( "Export as Open Office 1.3.x Presentation (still experimental)" ), QPixmap(), tr( "Export (OO Presentation)" +QString("...")), 0, this, "exportOOPresentation" );
+		connect( a, SIGNAL( activated() ), this, SLOT( fileExportOOPresentation() ) );
+		a->addTo( exportMenu );
+	}
+
+	a = new QAction( tr( "Export (XML)" ), QPixmap(), tr( "Export (XML)" )+QString("..."),  0, this, "exportXML" );
     connect( a, SIGNAL( activated() ), this, SLOT( fileExportXML() ) );
     a->addTo( exportMenu );
 	
     if (settings.readBoolEntry( "/vym/mainwindow/showTestMenu",false)) 
 	{
-		a = new QAction( tr( "Export HTML" ), QPixmap(), tr( "Export HTML" ), 0, this, "exportHTML"+QString("...") );
+		a = new QAction( tr( "Export HTML" ), QPixmap(), tr( "Export (HTML)" )+QString("..."), 0, this, "exportHTML");
 		connect( a, SIGNAL( activated() ), this, SLOT( fileExportHTML() ) );
 		a->addTo( exportMenu );
 	}
@@ -1723,6 +1738,18 @@
 		currentMapEditor()->exportASCII();	
 }
 
+void Main::fileExportLaTeX()
+{
+	if (currentMapEditor())
+		currentMapEditor()->exportLaTeX();	
+}
+
+void Main::fileExportOOPresentation()
+{
+	if (currentMapEditor())
+		currentMapEditor()->exportOOPresentation();	
+}
+
 void Main::fileCloseMap()
 {
 	if (currentMapEditor())
@@ -1817,8 +1844,10 @@
 		currentMapEditor()->undo();
 }
 
-void Main::editRedo()	    // TODO
+void Main::editRedo()	   
 {
+	if (currentMapEditor())
+		currentMapEditor()->redo();
 }
 
 void Main::editCopy()
diff -r 2cf3413b6ac9 -r 30b22f7bd009 mainwindow.h
--- a/mainwindow.h	Tue Sep 06 15:04:50 2005 +0000
+++ b/mainwindow.h	Mon Sep 12 19:52:51 2005 +0000
@@ -70,6 +70,8 @@
     void fileExportXHTML();
     void fileExportImage(int);
     void fileExportASCII();
+    void fileExportLaTeX();
+    void fileExportOOPresentation();
     void fileCloseMap();
     void filePrint();
     void fileExitVYM();
diff -r 2cf3413b6ac9 -r 30b22f7bd009 mapeditor.cpp
--- a/mapeditor.cpp	Tue Sep 06 15:04:50 2005 +0000
+++ b/mapeditor.cpp	Mon Sep 12 19:52:51 2005 +0000
@@ -355,6 +355,11 @@
 	fileName="unnamed";
 	mapName="";
 
+
+	undosTotal=15;	
+	undosAvail=0;	
+	undoNum=0;
+	
 	// Initialize find routine
 	itFind=NULL;				
 	EOFind=false;
@@ -480,21 +485,26 @@
 {
 	// Create unique temporary directories
 	char tmpdir[]="/tmp/vym-XXXXXX";	
-	bakMapDir=mkdtemp(tmpdir);
-	makeSubDirs(bakMapDir);
-	// FIXME set permissions and maybe use QT method for portability
+	// TODO set permissions and maybe use QT method for portability
+	tmpMapDir=mkdtemp(tmpdir);
+	QString bakMapDir;
+	for (int i=undosTotal;i>0;i--)
+	{
+		bakMapDir=tmpMapDir+QString("/undo-%1").arg(i);
+		makeSubDirs(bakMapDir);
+	}	
 }
 
 void MapEditor::delTmpDirs()
 {
-	//FIXME delete tmp directory, better use QT methods here:
-	system ( "rm -rf "+ bakMapDir );
+	removeDir (QDir(tmpMapDir));
 }
 
 
 void MapEditor::makeSubDirs(const QString &s)
 {
 	QDir d(s);
+	d.mkdir(s);
 	d.mkdir ("images");	
 	d.mkdir ("flags");	
 }
@@ -502,7 +512,7 @@
 
 QString MapEditor::saveToDir(const QString &tmpdir, const QString &prefix, bool writeflags, const QPoint &offset, LinkableMapObj *saveSelection)
 {
-	// tmpdir		temporary directory to which data will be writte
+	// tmpdir		temporary directory to which data will be written
 	// prefix		mapname, which will be appended to images etc.
 	// writeflags	Only write flags for "real" save of map, not undo
 	// offset		offset of bbox of whole map in canvas. 
@@ -560,7 +570,7 @@
 		else	
 			if (selection && typeid(*selection)==typeid(BranchObj))
 				// This is used if selected branch is saved from mainwindow
-				s+=((BranchObj*)(selection))->saveToDir(tmpdir,prefix,offset);
+				s+=((BranchObj*)selection)->saveToDir(tmpdir,prefix,offset);
 	}
 
 	// Save local settings
@@ -580,44 +590,70 @@
 
 void MapEditor::saveState()
 {
-	saveState (CompleteMap,NULL,"","");
+	// Save complete map
+	saveState (CompleteMap,"",NULL,"",NULL);
 }
 
 void MapEditor::saveState(LinkableMapObj *undoSel)
 {
-	saveState (PartOfMap,undoSel,"","");
+	// save the given part of the map 
+	saveState (PartOfMap,"",undoSel,"",NULL);
 }
 
-void MapEditor::saveState(const QString & uc, const QString &rc)
+void MapEditor::saveState(const QString &uc, const QString &rc)
 {
-	LinkableMapObj *undoSel;
+	// selection does not change during action,
+	// so just save commands for undo and redo
+	LinkableMapObj *unsel;
 	if (selection)
-		undoSel=selection;
+		unsel=selection;
 	else
-		undoSel=NULL;
-	saveState (UndoCommand,undoSel,uc,rc);
+		unsel=NULL;
+	saveState (UndoCommand,uc,unsel,rc,unsel);
 }
 
-void MapEditor::saveState(const SaveMode &savemode, LinkableMapObj *undoSel, const QString &undoCom, const QString &redoCom)
+void MapEditor::saveState(const QString & uncom, LinkableMapObj *unsel) 
 {
+	saveState (UndoCommand,uncom,unsel,"FIXME-redoCom",NULL);
+}
+
+void MapEditor::saveState(const SaveMode &savemode, const QString &undoCom, LinkableMapObj *undoSel, const QString &redoCom, LinkableMapObj *redoSel)
+{
+	// Main saveState
+
 	if (blockSaveState) return;
 
+	/* TODO remove after testing
+	cout << "ME::saveState()  begin\n"<<endl;
+	cout << "    undosTotal="<<undosTotal<<endl;
+	cout << "    undosAvail="<<undosAvail<<endl;
+	cout << "       undoNum="<<undoNum<<endl;
+	cout << "    ---------------------------"<<endl;
+	*/
 	setChanged();
 
+	// Find out current undo directory
+	if (undosAvail<undosTotal) undosAvail++;
+	undoNum++;
+	if (undoNum>undosTotal) undoNum=1;
+	
+	QString backupXML;
+	QString bakMapDir=QDir::convertSeparators (QString(tmpMapDir+"/undo-%1").arg(undoNum));
+	QString bakMapPath=bakMapDir+"/map.xml";
+
+
 	// Save current selection 
-	redoCommand=redoCom;
-	if (selection)
-		redoSelection=selection->getSelectString();
-	else	
-		redoSelection="";
+	QString redoSelection="";
+	if (redoSel)
+		redoSelection=redoSel->getSelectString();
 
 	// Save the object, which should be undone
+	QString undoSelection="";
 	if (undoSel)
 		undoSelection=undoSel->getSelectString();
-	else
-		undoSelection="";
 		
 	// Save depending on how much needs to be saved	
+	QString undoCommand="";
 	if (savemode==UndoCommand)
 	{
 		undoCommand=undoCom;
@@ -625,28 +661,43 @@
 	}	
 	else if (savemode==PartOfMap && undoSel)
 	{
-		undoCommand="undoPart (\""+undoSelection+"\")";
+		undoCommand="undoPart (\""+ undoSelection+"\",\""+bakMapPath+"\")";
 		backupXML=saveToDir (bakMapDir,mapName+"-",false, QPoint (),undoSel);
 	} else
 	{
-		undoCommand="undoMap ()";
+		undoCommand="undoMap (\""+bakMapPath+"\")";
 		backupXML=saveToDir (bakMapDir,mapName+"-",false, QPoint (),NULL);
 		undoSelection="";
 	}
-	/* FIXME testing
-	cout << "ME::saveState()\n";
-	cout << "  undoCom="<<undoCommand<<endl;
-	cout << "  undoSel="<<undoSelection<<endl;
-	cout << "  ---------------------------"<<endl;
-	cout << "  redoCom="<<redoCommand<<endl;
-	cout << "  redoSel="<<redoSelection<<endl<<endl;
+	if (!backupXML.isEmpty())
+		// Write XML Data to disk
+		saveStringToDisk (QString(bakMapPath),backupXML);
+
+	SimpleSettings set;
+	set.setEntry (QString("undoCommand"),undoCommand);
+	set.setEntry (QString("undoSelection"),undoSelection);
+	set.setEntry (QString("redoCommand"),redoCom);
+	set.setEntry (QString("redoSelection"),redoSelection);
+	set.writeSettings(QString(bakMapDir+"/commands"));
+
+	/* TODO remove after testing
+	cout << "          into="<< bakMapDir<<endl;
+	cout << "    undosAvail="<<undosAvail<<endl;
+	cout << "       undoNum="<<undoNum<<endl;
+	cout << "    ---------------------------"<<endl;
+	cout << "    undoCom="<<undoCommand<<endl;
+	cout << "    undoSel="<<undoSelection<<endl;
+	cout << "    ---------------------------"<<endl;
+	cout << "    redoCom="<<redoCom<<endl;
+	cout << "    redoSel="<<redoSelection<<endl;
+	cout << "    ---------------------------"<<endl<<endl;
 	*/
 }
 
 void MapEditor::parseAtom(const QString &atom)
 {
 	API api;
-	QString s;
+	QString s,t;
 	int x,y;
 	bool ok;
 
@@ -655,7 +706,7 @@
 	QString com=api.command();
 	
 	// External commands
-	if (com==QString("moveBranchUp"))
+	if (com=="moveBranchUp")
 		moveBranchUp();
 	else if (com=="moveBranchDown")
 		moveBranchDown();
@@ -686,16 +737,16 @@
 						// Get number in parent
 						x=api.parInt (ok,1);
 						if (ok)
-							((BranchObj*)(selection))->moveBranchTo ((BranchObj*)(dst),x);
+							((BranchObj*)selection)->moveBranchTo ((BranchObj*)(dst),x);
 					} else if (typeid(*dst) == typeid(MapCenterObj) ) 
 					{
-						((BranchObj*)(selection))->moveBranchTo ((BranchObj*)(dst),-1);
+						((BranchObj*)selection)->moveBranchTo ((BranchObj*)(dst),-1);
 						// Get coordinates of mainbranch
 						x=api.parInt (ok,2);
 						if (ok)
 						{
 							y=api.parInt (ok,3);
-							if (ok) ((BranchObj*)(selection))->move (x,y);
+							if (ok) ((BranchObj*)selection)->move (x,y);
 						}
 					}	
 				}	
@@ -723,18 +774,18 @@
 			if (ok) setVymLink(s);
 		}	
 	}
-
 	// Internal commands, used for undo etc.	
 	else if (com==QString("undoMap"))
 	{
-		if (api.checkParamCount(0))
-			undoXML("");
+		if (api.checkParamCount(1))
+			undoXML("",api.parString (ok,0));
 	} else if (com==QString("undoPart"))
 	{
-		if (api.checkParamCount(1))
+		if (api.checkParamCount(2))
 		{
 			s=api.parString (ok,0);
-			undoXML(s);
+			t=api.parString (ok,1);
+			undoXML(s,t);	
 		}
 	} else if (com=="select")
 		if (api.checkParamCount(1))
@@ -743,7 +794,10 @@
 			if (ok) select (s);
 		}	
 	else
+	{
 		api.setError ("Unknown command in: "+atom);
+		cout << "ME::parse   api should have error now...\n";
+	}
 
 	// Any errors?
 	if (api.error())
@@ -908,8 +962,10 @@
 		handler.setMapEditor( this );
 		handler.setTmpDir (filePath.left(filePath.findRev("/",-1)));	// needed to load files with rel. path
 		handler.setLoadMode (lmode);
+		blockSaveState=true;
 		bool ok = reader.parse( source );
 		blockReposition=false;
+		blockSaveState=false;
 		file.close();
 		if ( ok ) 
 		{
@@ -955,35 +1011,14 @@
 		fname=fileName;
 
 
-	// Check if fname is writeable
-	QFile file( fileDir+fname);
-	if (!file.open( IO_WriteOnly ) ) 
-	{
-		QMessageBox::critical( 0, tr( "Critical Save Error" ),
-					   tr("Couldn't write to ") +fileDir+fname);
-		return 1;
-	}	
-	file.close();
-
 	QString saveFile;
 	if (savemode==CompleteMap || selection==NULL)
 		saveFile=saveToDir (fileDir,mapName+"-",true,QPoint(),NULL);
 	else	
 		saveFile=saveToDir (fileDir,mapName+"-",true,QPoint(),selection);
 
-	file.setName ( fileDir  + fname);
-	if ( !file.open( IO_WriteOnly ) )
-	{
-		// This should neverever happen
-		QMessageBox::critical(0, tr("Critcal Save error"),"MapEditor::save() Couldn't open "+file.name());
+	if (!saveStringToDisk(fileDir+fname,saveFile))
 		return 1;
-	}	
-
-	// Write it finally, and write in UTF8, no matter what 
-	QTextStream ts( &file );
-	ts.setEncoding (QTextStream::UnicodeUTF8);
-	ts << saveFile;
-	file.close();
 
 	if (returnCode==0)
 	{
@@ -1074,7 +1109,7 @@
 				frame->setZ(0);
 				frame->show();    
 			}		
-			/* FIXME testing
+			/* TODO remove after testing 
 			QCanvasLine *l=new QCanvasLine (mapCanvas);
 			l->setPoints (0,0,mapRect.width(),mapRect.height());
 			l->setPen (QPen(QColor(black), 1));
@@ -1227,6 +1262,93 @@
 	}
 }
 
+void MapEditor::exportLaTeX()
+{
+	// FIXME still experimental
+	QFileDialog *fd=new QFileDialog( this, tr("VYM - Export (LaTex)"));
+	fd->addFilter ("TEX (*.tex)");
+	fd->setCaption("VYM - Export (LaTex) (still experimental)");
+	fd->setMode( QFileDialog::AnyFile );
+	fd->show();
+
+	if ( fd->exec() == QDialog::Accepted )
+	{
+		if (QFile (fd->selectedFile()).exists() )
+		{
+			QMessageBox mb( "VYM",
+				tr("The file ") + fd->selectedFile() + 
+				tr(" exists already. Do you want to overwrite it?"),
+			QMessageBox::Warning,
+			QMessageBox::Yes | QMessageBox::Default,
+			QMessageBox::Cancel | QMessageBox::Escape,
+			QMessageBox::NoButton );
+
+			mb.setButtonText( QMessageBox::Yes, tr("Overwrite") );
+			mb.setButtonText( QMessageBox::No, tr("Cancel"));
+			Export ex;
+			switch( mb.exec() ) 
+			{
+				case QMessageBox::Yes:
+					// save 
+					break;;
+				case QMessageBox::Cancel:
+					// do nothing
+					return;
+					break;
+			}
+		}
+		Export ex;
+		ex.setPath (fd->selectedFile() );
+		ex.setMapCenter(mapCenter);
+		ex.exportLaTeX();
+	}
+}
+
+void MapEditor::exportOOPresentation()
+{
+	// FIXME still experimental
+	/*
+	QFileDialog *fd=new QFileDialog( this, tr("VYM - Export (Open Office 1.3.x Presentation)"));
+	fd->addFilter ("Open Office 1.3.x presentation (*.sxi)");
+	fd->setCaption("VYM - Export (Open Office 1.3.x presentation) (still experimental)");
+	fd->setMode( QFileDialog::AnyFile );
+	fd->show();
+
+	if ( fd->exec() == QDialog::Accepted )
+	{
+		if (QFile (fd->selectedFile()).exists() )
+		{
+			QMessageBox mb( "VYM",
+				tr("The file ") + fd->selectedFile() + 
+				tr(" exists already. Do you want to overwrite it?"),
+			QMessageBox::Warning,
+			QMessageBox::Yes | QMessageBox::Default,
+			QMessageBox::Cancel | QMessageBox::Escape,
+			QMessageBox::NoButton );
+
+			mb.setButtonText( QMessageBox::Yes, tr("Overwrite") );
+			mb.setButtonText( QMessageBox::No, tr("Cancel"));
+			Export ex;
+			switch( mb.exec() ) 
+			{
+				case QMessageBox::Yes:
+					// save 
+					break;;
+				case QMessageBox::Cancel:
+					// do nothing
+					return;
+					break;
+			}
+		}
+		*/
+		Export ex;
+		//ex.setPath (fd->selectedFile() );
+		ex.setMapCenter(mapCenter);
+		ex.exportOOPresentation();
+//	}
+}
+
+
 
 void MapEditor::exportXML(const QString &dir)
 {
@@ -1282,7 +1404,7 @@
 			to=clipboardME->getMapCenter()->getLastBranch();
 			if (to) 
 			{
-				from=(BranchObj*)(selection);
+				from=(BranchObj*)selection;
 				to->copy(from);
 
 				// keep position relative to parent
@@ -1310,7 +1432,7 @@
 			to=clipboardME->getMapCenter()->getLastFloatImage();
 			if (to) 
 			{
-				from=(FloatImageObj*)(selection);
+				from=(FloatImageObj*)selection;
 				to->copy(from);
 
 				// select data in clipboard
@@ -1319,9 +1441,7 @@
 				// repositioning makes testing nicer,
 				// but is not needed usually:
 				if (clipboardME->isVisible())
-				{
 					clipboardME->getMapCenter()->reposition();  
-				}	
 				else
 					clipboardME->hide();
 			}
@@ -1329,36 +1449,143 @@
 	}	    
 }
 
+void MapEditor::redo()
+{
+	// Finish open lineEdits
+	if (lineedit) finishedLineEditNoSave();
+
+	blockSaveState=true;
+	
+	// Find out current undo directory
+	QString bakMapDir=QDir::convertSeparators (QString(tmpMapDir+"/undo-%1").arg(undoNum));
+
+	// Restore variables
+	QString undoCommand;
+	QString undoSelection;
+	QString redoCommand;
+	QString redoSelection;
+	SimpleSettings set;
+	set.readSettings(QString(bakMapDir+"/commands"));
+	undoCommand=set.readEntry ("undoCommand");
+	undoSelection=set.readEntry ("undoSelection");
+	redoCommand=set.readEntry ("redoCommand");
+	redoSelection=set.readEntry ("redoSelection");
+
+	// select  object before redo
+	if (!redoSelection.isEmpty())
+		select (redoSelection);
+
+/* TODO remove testing
+	cout << "ME::redo() begin\n";
+	cout << "    undosTotal="<<undosTotal<<endl;
+	cout << "    undosAvail="<<undosAvail<<endl;
+	cout << "       undoNum="<<undoNum<<endl;
+	cout << "    ---------------------------"<<endl;
+	cout << "    undoCom="<<undoCommand<<endl;
+	cout << "    undoSel="<<undoSelection<<endl;
+	cout << "    ---------------------------"<<endl;
+	cout << "    redoCom="<<redoCommand<<endl;
+	cout << "    redoSel="<<redoSelection<<endl;
+	cout << "    ---------------------------"<<endl;
+*/
+	parseAtom (undoCommand);
+	mapCenter->reposition();
+
+	//mapChanged=false;  FIXME  still needed???
+
+	//if (!redoSelection.isEmpty())
+	//	select (redoSelection);
+
+	undosAvail--;
+	if (undosAvail<1)
+		// Undo not longer available now
+		actionEditUndo->setEnabled (false);
+	else	
+		undoNum--; if (undoNum<1) undoNum=undosTotal;
+
+	blockSaveState=false;
+/* TODO remove testing
+	cout << "ME::redo() end\n";
+	cout << "    undosAvail="<<undosAvail<<endl;
+	cout << "       undoNum="<<undoNum<<endl;
+	cout << "    ---------------------------"<<endl<<endl;
+*/	
+}
+
 void MapEditor::undo()
 {
 	// Finish open lineEdits
 	if (lineedit) finishedLineEditNoSave();
 
+	blockSaveState=true;
+	
+	// Find out current undo directory
+	QString bakMapDir=QDir::convertSeparators (QString(tmpMapDir+"/undo-%1").arg(undoNum));
+
+	// Restore variables
+	QString undoCommand;
+	QString undoSelection;
+	QString redoCommand;
+	QString redoSelection;
+	SimpleSettings set;
+	set.readSettings(QString(bakMapDir+"/commands"));
+	undoCommand=  set.readEntry ("undoCommand");
+	undoSelection=set.readEntry ("undoSelection");
+	redoCommand=  set.readEntry ("redoCommand");
+	redoSelection=set.readEntry ("redoSelection");
+
 	// select  object before undo
 	if (!undoSelection.isEmpty())
 		select (undoSelection);
 
+/* TODO remove testing
+	cout << "ME::undo() begin\n";
+	cout << "    undosTotal="<<undosTotal<<endl;
+	cout << "    undosAvail="<<undosAvail<<endl;
+	cout << "       undoNum="<<undoNum<<endl;
+	cout << "    ---------------------------"<<endl;
+	cout << "    undoCom="<<undoCommand<<endl;
+	cout << "    undoSel="<<undoSelection<<endl;
+	cout << "    ---------------------------"<<endl;
+	cout << "    redoCom="<<redoCommand<<endl;
+	cout << "    redoSel="<<redoSelection<<endl;
+	cout << "    ---------------------------"<<endl;
+*/	
 	parseAtom (undoCommand);
 	mapCenter->reposition();
 
-	// Undo not longer available now
-	actionEditUndo->setEnabled (false);
-	mapChanged=false;
-
-	if (!redoSelection.isEmpty())
-		select (redoSelection);
+	//mapChanged=false;  FIXME  still needed???
+
+	//if (!redoSelection.isEmpty())
+	//	select (redoSelection);
+
+	undosAvail--;
+	if (undosAvail<1)
+		// Undo not longer available now
+		actionEditUndo->setEnabled (false);
+	else	
+		undoNum--; if (undoNum<1) undoNum=undosTotal;
+
+	blockSaveState=false;
+/* TODO remove testing
+	cout << "ME::undo() end\n";
+	cout << "    undosAvail="<<undosAvail<<endl;
+	cout << "       undoNum="<<undoNum<<endl;
+	cout << "    ---------------------------"<<endl<<endl;
+*/
 }
 
-void MapEditor::undoXML(const QString &undoSel)
+void MapEditor::undoXML(const QString &undoSel, const QString &bakMapPath)
 {
-	QDir d;
-	d.setPath(bakMapDir);
+	QString bakMapDir=bakMapPath.left(bakMapPath.findRev("/"));
+	QDir d(bakMapDir);
+	QFile file (bakMapPath);
+
 	if (d.exists() )
 	{
 		// We need to parse saved XML data
 		mapBuilderHandler handler;
-		QXmlInputSource source;
-		source.setData(backupXML);
+		QXmlInputSource source( file);
 		QXmlSimpleReader reader;
 		reader.setContentHandler( &handler );
 		reader.setErrorHandler( &handler );
@@ -1375,15 +1602,13 @@
 			handler.setLoadMode (ImportReplace);
 		}	
 		blockReposition=true;
-		blockSaveState=true;
 		bool ok = reader.parse( source );
 		blockReposition=false;
-		blockSaveState=false;
 		if (! ok ) 
 		{	
 			// This should never ever happen
 			QMessageBox::critical( 0, tr( "Critical Parse Error by reading backupFile" ),
-								   tr( handler.errorProtocol() )+" in "+backupXML );
+								   tr( handler.errorProtocol() )+" in "+bakMapDir );
 		}
 	} else	
 	{
@@ -1414,13 +1639,13 @@
 				((BranchObj*)(returnLMO))->move2RelPos(normalise(fromLMO->getRelPos() ) );
 			}     
 			if (typeid(*selection) == typeid(BranchObj)) 
-					returnLMO=((BranchObj*)(selection))->addBranch((BranchObj*)(fromLMO) );
+					returnLMO=((BranchObj*)selection)->addBranch((BranchObj*)(fromLMO) );
 		}
 		
 		if (typeid(*fromLMO) == typeid(FloatImageObj) &&
 			(typeid(*selection) == typeid (BranchObj) || 
 			 typeid(*selection)==typeid(MapCenterObj)) )
-			returnLMO=((BranchObj*) (selection))->addFloatImage ((FloatImageObj*)(fromLMO));
+			returnLMO=((BranchObj*) selection)->addFloatImage ((FloatImageObj*)(fromLMO));
 		
 	}	    
 	return returnLMO;
@@ -1436,7 +1661,7 @@
 	if (selection != NULL) {
 		if (typeid(*selection) == typeid(BranchObj) ) 
 		{
-			bo=(BranchObj*)(selection);
+			bo=(BranchObj*)selection;
 			par=(BranchObj*)(bo->getParObj());
 			bo->unselect();
 			selection=NULL;
@@ -1446,7 +1671,7 @@
 		}
 		if (typeid(*selection) == typeid(FloatImageObj) ) 
 		{
-			FloatImageObj* fio=(FloatImageObj*)(selection);
+			FloatImageObj* fio=(FloatImageObj*)selection;
 			par=(BranchObj*)(fio->getParObj());
 			fio->unselect();
 			selection=NULL;
@@ -1479,7 +1704,7 @@
 	// FIXME  no saveState, because this is only internal at undo so far
 	if (selection) selection->move(x,y);
 	if (typeid(*selection) == typeid(FloatImageObj))
-		((FloatImageObj*)(selection))->setRelPos();
+		((FloatImageObj*)selection)->setRelPos();
 }
 
 void MapEditor::moveBranchUp()
@@ -1491,12 +1716,12 @@
 	BranchObj* par;
 	if (typeid(*selection) == typeid(BranchObj)  ) 
 	{
-		bo=(BranchObj*)(selection);
+		bo=(BranchObj*)selection;
 		par=(BranchObj*)(bo->getParObj());
 		selection->unselect();
 		selection=par->moveBranchUp (bo);
 		selection->select();
-		saveState("moveBranchDown ()",bo->getSelectString());
+		saveState("moveBranchDown ()",bo);
 		mapCenter->reposition();
 		ensureSelectionVisible();
 	}
@@ -1511,12 +1736,12 @@
 	BranchObj* par;
 	if (typeid(*selection) == typeid(BranchObj)  ) 
 	{
-		bo=(BranchObj*)(selection);
+		bo=(BranchObj*)selection;
 		par=(BranchObj*)(bo->getParObj());
 		selection->unselect(); 
 		selection=par->moveBranchDown(bo);
 		selection->select();
-		saveState("moveBranchUp ()",bo->getSelectString());
+		saveState("moveBranchUp ()",bo);
 		mapCenter->reposition();
 		ensureSelectionVisible();
 	}	
@@ -1531,8 +1756,8 @@
 		 (typeid(*selection) == typeid(BranchObj) || 
 		  typeid(*selection) == typeid(MapCenterObj) ) ) 
 	{
-		editingBO=(BranchObj*)(selection);
-		saveState("setHeading (\""+((BranchObj*)(selection))->getHeading()+"\")",editingBO->getSelectString() );
+		editingBO=(BranchObj*)selection;
+		saveState("setHeading (\""+((BranchObj*)selection)->getHeading()+"\")",editingBO );
 
 		ensureSelectionVisible();
 		QPoint p = worldMatrix().map(QPoint (editingBO->x(),editingBO->y()));
@@ -1543,7 +1768,6 @@
 		if (actionSettingsAutoselectText->isOn() && !s.isEmpty() && actionSettingsPasteNewHeading->isOn() )
 			lineedit->selectAll();
 		lineedit->show();
-
 		lineedit->grabKeyboard();
 		lineedit->setFocus();
 	}				
@@ -1556,7 +1780,7 @@
 		 (typeid(*selection) == typeid(BranchObj) || 
 		  typeid(*selection) == typeid(MapCenterObj) ) ) 
 	{
-		((BranchObj*)(selection))->setHeading(s);
+		((BranchObj*)selection)->setHeading(s);
 		mapCenter->reposition();
 		adjustCanvasSize();
 		ensureSelectionVisible();
@@ -1570,7 +1794,7 @@
 		 (typeid(*selection) == typeid(BranchObj) || 
 		  typeid(*selection) == typeid(MapCenterObj) ) ) 
 	{
-		((BranchObj*)(selection))->setURL(s);
+		((BranchObj*)selection)->setURL(s);
 		mapCenter->reposition();
 		adjustCanvasSize();
 		ensureSelectionVisible();
@@ -1584,7 +1808,7 @@
 		 (typeid(*selection) == typeid(BranchObj) || 
 		  typeid(*selection) == typeid(MapCenterObj) ) ) 
 	{
-		((BranchObj*)(selection))->setVymLink(s);
+		((BranchObj*)selection)->setVymLink(s);
 		mapCenter->reposition();
 		adjustCanvasSize();
 		ensureSelectionVisible();
@@ -1602,7 +1826,7 @@
 	{
 		saveState(selection);	//FIXME undoCommand
 
-		BranchObj* bo1 = (BranchObj*) (selection);
+		BranchObj* bo1 = (BranchObj*) selection;
 		bool wasScrolled=false;
 		BranchObj *newbo=NULL;
 		if (pos==0)
@@ -1640,7 +1864,7 @@
 			selection->select();
 			if (actionSettingsPasteNewHeading->isOn() )
 			{
-				BranchObj *bo2= (BranchObj*)(selection);
+				BranchObj *bo2= (BranchObj*)selection;
 				bo2->setHeading("");
 			}	
 			if (actionSettingsAutoedit->isOn() )
@@ -1667,7 +1891,7 @@
 	{
 		saveState(selection);
 
-		BranchObj* bo1 = (BranchObj*) (selection);
+		BranchObj* bo1 = (BranchObj*) selection;
 		bool wasScrolled=false;
 		BranchObj *newbo=NULL;
 		BranchObj *parbo=(BranchObj*)(selection->getParObj());
@@ -1678,7 +1902,7 @@
 		} 
 
 		LinkableMapObj *oldselection=selection;
-		((BranchObj*)(selection))->moveBranchTo (newbo,-1);
+		((BranchObj*)selection)->moveBranchTo (newbo,-1);
 
 		mapCenter->reposition();
 		adjustCanvasSize();
@@ -1690,7 +1914,7 @@
 			selection->select();
 			if (actionSettingsPasteNewHeading->isOn() )
 			{
-				BranchObj *bo2= (BranchObj*)(selection);
+				BranchObj *bo2= (BranchObj*)selection;
 				bo2->setHeading("");
 			}	
 			if (actionSettingsAutoedit->isOn() )
@@ -1854,7 +2078,7 @@
 					b=select (s);
 					if (b)
 					{	
-						if ( ((BranchObj*)(selection))->countBranches()>0)
+						if ( ((BranchObj*)selection)->countBranches()>0)
 							s+=",bo:0";
 						else	
 							break;
@@ -1933,8 +2157,8 @@
 				{
 					b=select (s);
 					if (b)
-						if ( ((BranchObj*)(selection))->countBranches()>0)
-							s+=",bo:"+ QString ("%1").arg( ((BranchObj*)(selection))->countBranches()-1 );
+						if ( ((BranchObj*)selection)->countBranches()>0)
+							s+=",bo:"+ QString ("%1").arg( ((BranchObj*)selection)->countBranches()-1 );
 						else	
 							break;
 					else
@@ -2001,7 +2225,7 @@
 	{
 		if (typeid(*selection) == typeid(MapCenterObj))
 		{
-			par=  (BranchObj*) (selection);
+			par=  (BranchObj*) selection;
 			bo=par->getLastSelectedBranch();
 			if (bo)
 			{
@@ -2037,7 +2261,7 @@
 			{
 				if (typeid(*selection) == typeid(BranchObj) )
 				{
-					bo=((BranchObj*)(selection))->getLastSelectedBranch();
+					bo=((BranchObj*)selection)->getLastSelectedBranch();
 					if (bo) 
 					{
 						selection->unselect();
@@ -2064,7 +2288,7 @@
 	{
 		if (typeid(*selection) == typeid(MapCenterObj))
 		{
-			par=  (BranchObj*) (selection);
+			par=  (BranchObj*) selection;
 			bo=par->getLastSelectedBranch();
 			if (bo)
 			{
@@ -2097,7 +2321,7 @@
 			{
 				if (typeid(*selection) == typeid(BranchObj) )
 				{
-					bo=((BranchObj*)(selection))->getLastSelectedBranch();
+					bo=((BranchObj*)selection)->getLastSelectedBranch();
 					if (bo) 
 					{
 						selection->unselect();
@@ -2123,7 +2347,7 @@
 	if (selection) {
 		if (typeid(*selection) == typeid(BranchObj))
 		{
-			bo1=  (BranchObj*) (selection);
+			bo1=  (BranchObj*) selection;
 			par=(BranchObj*)(bo1->getParObj());
 			bo2=par->getFirstBranch();
 			if (bo2) {
@@ -2148,7 +2372,7 @@
 	if (selection) {
 		if (typeid(*selection) == typeid(BranchObj))
 		{
-			bo1=  (BranchObj*) (selection);
+			bo1=  (BranchObj*) selection;
 			par=(BranchObj*)(bo1->getParObj());
 			bo2=par->getLastBranch();
 			if (bo2) {
@@ -2190,7 +2414,7 @@
 		if (typeid(*selection) == typeid(BranchObj) ||
 			typeid(*selection) == typeid(MapCenterObj))
 		{
-			BranchObj *bo=(BranchObj*)(selection);
+			BranchObj *bo=(BranchObj*)selection;
 			actColor=bo->getColor(); 
 		}    
 	}
@@ -2205,7 +2429,7 @@
 			typeid(*selection) == typeid(MapCenterObj))
 		{
 			saveState(selection);	//FIXME undoCommand
-			BranchObj *bo=(BranchObj*)(selection);
+			BranchObj *bo=(BranchObj*)selection;
 			bo->setColor(actColor, false); // color links, color childs
 		}    
 	}
@@ -2219,7 +2443,7 @@
 			typeid(*selection) == typeid(MapCenterObj))
 		{
 			saveState(selection);
-			BranchObj *bo=(BranchObj*)(selection);
+			BranchObj *bo=(BranchObj*)selection;
 			bo->setColor(actColor, true); // color links, color childs
 		}    
 	}
@@ -2231,7 +2455,7 @@
 	if (selection)
 	{
 		saveState(selection);// FIXME undoCommand	
-		((BranchObj*)(selection))->toggleStandardFlag (f,actionSettingsUseFlagGroups);
+		((BranchObj*)selection)->toggleStandardFlag (f,actionSettingsUseFlagGroups);
 	}	
 }
 
@@ -2263,7 +2487,7 @@
 			{
 				if (selection!=itFind) 
 				{
-					if (selection) ((BranchObj*)(selection))->unselect();
+					if (selection) ((BranchObj*)selection)->unselect();
 					selection=itFind;
 					selection->select();
 					adjustCanvasSize();
@@ -2278,7 +2502,7 @@
 			// Searching in Heading
 			if (searching && itFind->getHeading().contains (s,cs) ) 
 			{
-				if (selection) ((BranchObj*)(selection))->unselect();
+				if (selection) ((BranchObj*)selection)->unselect();
 				selection=itFind;
 				selection->select();
 				adjustCanvasSize();
@@ -2295,7 +2519,7 @@
 	if (!searching)
 	{
 		adjustCanvasSize();
-		return (BranchObj*)(selection);
+		return (BranchObj*)selection;
 	}	else
 		return NULL;
 }
@@ -2313,7 +2537,7 @@
 		if (typeid(*selection) == typeid(BranchObj) ||
 			typeid(*selection) == typeid(MapCenterObj))
 		{
-			QString url=((BranchObj*)(selection))->getURL();
+			QString url=((BranchObj*)selection)->getURL();
 
 			QProcess *proc = new QProcess( this );
 
@@ -2334,7 +2558,7 @@
 			typeid(*selection) == typeid(MapCenterObj)) )
 	{		
 		bool ok;
-		BranchObj *bo=(BranchObj*)(selection);
+		BranchObj *bo=(BranchObj*)selection;
 		QString text = QInputDialog::getText(
 				"VYM", tr("Enter URL:"), QLineEdit::Normal,
 				bo->getURL(), &ok, this );
@@ -2353,7 +2577,7 @@
 	if (selection && (typeid(*selection) == typeid(BranchObj) ||
 			typeid(*selection) == typeid(MapCenterObj)) )
 	{		
-		BranchObj *bo=(BranchObj*)(selection);
+		BranchObj *bo=(BranchObj*)selection;
 		saveState("setURL (\""+bo->getURL()+"\")","setURL (\""+bo->getHeading()+"\")");	
 		bo->setURL (bo->getHeading());
 		updateActions();
@@ -2365,7 +2589,7 @@
 	if (selection && (typeid(*selection) == typeid(BranchObj) ||
 			typeid(*selection) == typeid(MapCenterObj)) )
 	{		
-		BranchObj *bo=(BranchObj*)(selection);
+		BranchObj *bo=(BranchObj*)selection;
 		QString url= "https://bugzilla.novell.com/show_bug.cgi?id="+bo->getHeading();
 		saveState("setURL (\""+bo->getURL()+"\")","setURL (\""+url+"\")");	
 		bo->setURL (url);
@@ -2378,7 +2602,7 @@
 	if (selection && (typeid(*selection) == typeid(BranchObj) ||
 			typeid(*selection) == typeid(MapCenterObj)) )
 	{		
-		BranchObj *bo=(BranchObj*)(selection);
+		BranchObj *bo=(BranchObj*)selection;
 		QFileDialog *fd=new QFileDialog( this,tr("VYM - Link to another map"));
 		fd->addFilter (QString (tr("vym map") + " (*.vym)"));
 		fd->setCaption(tr("VYM - Link to another map"));
@@ -2404,7 +2628,7 @@
 	if (selection && (typeid(*selection) == typeid(BranchObj) ||
 			typeid(*selection) == typeid(MapCenterObj)) )
 	{		
-		BranchObj *bo=(BranchObj*)(selection);
+		BranchObj *bo=(BranchObj*)selection;
 		saveState("setVymLink (\""+bo->getVymLink()+"\")","setVymLink (\"\")");	
 		bo->setVymLink ("" );
 		updateActions();
@@ -2419,7 +2643,7 @@
 	if (selection && (typeid(*selection) == typeid(BranchObj) ||
 			typeid(*selection) == typeid(MapCenterObj)) )
 	{		
-		return ((BranchObj*)(selection))->getVymLink();
+		return ((BranchObj*)selection)->getVymLink();
 	}
 	return "";
 	
@@ -2429,7 +2653,7 @@
 {
 	if (selection && (typeid(*selection) == typeid(BranchObj) ))
 	{		
-		BranchObj* bo=(BranchObj*)(selection);
+		BranchObj* bo=(BranchObj*)selection;
 		BranchObj* par=(BranchObj*)(bo->getParObj());
 		if (bo->getDepth()==1)
 			saveState();
@@ -2448,7 +2672,7 @@
 	if (selection && (typeid(*selection) == typeid(BranchObj) ))
 	{		
 		saveState(selection->getParObj());
-		((BranchObj*)(selection))->removeChilds();
+		((BranchObj*)selection)->removeChilds();
 		mapCenter->reposition();
 	}	
 }
@@ -2537,7 +2761,7 @@
 		if ( (typeid(*selection) == typeid(BranchObj)) || 
 			(typeid(*selection) == typeid(MapCenterObj))  )
 		{
-			BranchObj *bo=(BranchObj*)(selection);
+			BranchObj *bo=(BranchObj*)selection;
 			// Take care of links
 			if (bo->countXLinks()==0)
 			{
@@ -2622,7 +2846,7 @@
 				a->setEnabled(false);
 			actionEditDelete->setEnabled (true);
 			actionEditToggleFloatExport->setOn
-				( ((FloatImageObj*)(selection))->getFloatExport() );
+				( ((FloatImageObj*)selection)->getFloatExport() );
 			actionFormatHideLinkUnselected->setOn
 				( selection->getHideLinkUnselected());
 		}
@@ -2649,11 +2873,9 @@
 void MapEditor::updateNoteFlag()
 {
 	if (selection)
-	{
 		if ( (typeid(*selection) == typeid(BranchObj)) || 
 			(typeid(*selection) == typeid(MapCenterObj))  )
 			((BranchObj*)selection)->updateNoteFlag();
-	}
 }
 
 void MapEditor::setLinkStyle (LinkStyle ls)
@@ -2762,7 +2984,7 @@
 {
 	if (selection && (typeid(*selection) == typeid(BranchObj)) )
 	{
-		BranchObj *bo=((BranchObj*)(selection));
+		BranchObj *bo=((BranchObj*)selection);
 		if (bo->countBranches()==0) return;
 		if (bo->getDepth()==0) return;
 		saveState(selection);
@@ -2789,7 +3011,7 @@
 		(typeid(*selection) == typeid(BranchObj)) || 
 		(typeid(*selection) == typeid(MapCenterObj))  )
 	{
-		BranchObj *bo=((BranchObj*)(selection));
+		BranchObj *bo=((BranchObj*)selection);
 
 		QFileDialog *fd=new QFileDialog( this,tr("vym - load image"));
 		fd->addFilter (QString (tr("Images") + " (*.png *.bmp *.xbm *.jpg *.png *.xpm *.gif *.pnm)"));
@@ -2823,7 +3045,7 @@
 	if (selection && 
 		(typeid(*selection) == typeid(FloatImageObj)) )
 	{
-		FloatImageObj *fio=((FloatImageObj*)(selection));
+		FloatImageObj *fio=((FloatImageObj*)selection);
 		const char* fmt = saveImageFormatMenu->text(item);
 
 		QFileDialog *fd=new QFileDialog( this, tr("vym - save image as") + fmt);
@@ -2877,7 +3099,7 @@
 		(typeid(*selection) == typeid(FloatImageObj))|| 
 		(typeid(*selection) == typeid(FloatObj)) )
 	{
-		FloatImageObj *fio=((FloatImageObj*)(selection));
+		FloatImageObj *fio=((FloatImageObj*)selection);
 		fio->setFloatExport (actionEditToggleFloatExport->isOn() );
 	}
 }
@@ -2971,7 +3193,7 @@
 		QString fn;
 		if ( fd->exec() == QDialog::Accepted )
 		{
-			BranchObj *bo=((BranchObj*)(selection));
+			BranchObj *bo=((BranchObj*)selection);
 			importDir (bo,QDir(fd->selectedFile()) );
 			mapCenter->reposition();
 			adjustCanvasSize();
@@ -2986,7 +3208,7 @@
 		(typeid(*selection) == typeid(BranchObj)) || 
 		(typeid(*selection) == typeid(MapCenterObj))  )
 	{
-		BranchObj *bo=((BranchObj*)(selection))->XLinkTargetAt(i);
+		BranchObj *bo=((BranchObj*)selection)->XLinkTargetAt(i);
 		if (bo) 
 		{
 			selection->unselect();
@@ -3003,7 +3225,7 @@
 		(typeid(*selection) == typeid(BranchObj)) || 
 		(typeid(*selection) == typeid(MapCenterObj))  )
 	{
-		XLinkObj *xlo=((BranchObj*)(selection))->XLinkAt(i);
+		XLinkObj *xlo=((BranchObj*)selection)->XLinkAt(i);
 		if (xlo) 
 		{
 			EditXLinkDialog dia;
@@ -3017,7 +3239,7 @@
 					setDefXLinkWidth (xlo->getWidth() );
 				}
 				if (dia.deleteXLink())
-					((BranchObj*)(selection))->deleteXLinkAt(i);
+					((BranchObj*)selection)->deleteXLinkAt(i);
 				saveState();	//FIXME undoCommand
 			}
 		}	
@@ -3030,7 +3252,7 @@
 	if (selection && 
 		(typeid(*selection) == typeid(BranchObj)) )
 	{
-		QString s=((BranchObj*)(selection))->getHeading();
+		QString s=((BranchObj*)selection)->getHeading();
 		parseAtom(s);
 	}
 }
@@ -3132,7 +3354,7 @@
 				if (selection && 
 					((typeid(*selection) == typeid(BranchObj)) || 
 					(typeid(*selection) == typeid(MapCenterObj)))  )
-				bo_begin=(BranchObj*)(selection);
+				bo_begin=(BranchObj*)selection;
 			if (bo_begin)	
 			{
 				drawingLink=true;
@@ -3165,7 +3387,7 @@
 		if (typeid(*selection)==typeid(BranchObj) ||
 			typeid(*selection)==typeid(MapCenterObj) )
 		{
-			QString foname=((BranchObj*)(selection))->getSystemFlagName(p);
+			QString foname=((BranchObj*)selection)->getSystemFlagName(p);
 			if (!foname.isEmpty())
 			{
 				// Do not move, if systemFlag clicked
@@ -3200,7 +3422,7 @@
 				if (typeid(*selection)==typeid(BranchObj) )
 				{
 					copyingObj=true;
-					mapCenter->addBranch ((BranchObj*)(selection));
+					mapCenter->addBranch ((BranchObj*)selection);
 					unselect();
 					selection=mapCenter->getLastBranch();
 					selection->select();
@@ -3252,7 +3474,7 @@
 
 		if (typeid(*selection) == typeid(FloatImageObj))
 		{
-			FloatObj *fo=(FloatObj*)(selection);
+			FloatObj *fo=(FloatObj*)selection;
 			saveState("move "+qpointToString(movingObj_orgPos),fo->getSelectString() );
 			if (fo->getLinkStyle()==StyleUndef) 
 			{
@@ -3304,7 +3526,6 @@
 				if (lmosel->getDepth()==1)
 				{
 					// depth==1, mainbranch
-					saveState("move "+qpointToString(movingObj_orgPos), lmosel->getSelectString() );
 					lmosel->move(p.x() -movingObj_start.x(), p.y()-movingObj_start.y() );		
 				} else
 				{
@@ -3389,13 +3610,13 @@
 		{	
 			if (e->state() & QMouseEvent::ShiftButton)
 			{
-				((BranchObj*)(selection))->setColor (((BranchObj*)(dst))->getColor(),false);
-				((BranchObj*)(selection))->setLinkColor ();
+				((BranchObj*)selection)->setColor (((BranchObj*)(dst))->getColor(),false);
+				((BranchObj*)selection)->setLinkColor ();
 			}	
 			else	
 			{
-				((BranchObj*)(selection))->setColor (((BranchObj*)(dst))->getColor(),true);
-				((BranchObj*)(selection))->setLinkColor ();
+				((BranchObj*)selection)->setColor (((BranchObj*)(dst))->getColor(),true);
+				((BranchObj*)selection)->setLinkColor ();
 			}	
 		} 
 		return;
@@ -3427,13 +3648,11 @@
 		// Check if we are over another branch, but ignore 
 		// any found LMOs, which are FloatObjs
 		dst=mapCenter->findMapObj(inverseWorldMatrix().map(e->pos() ), 
-			((LinkableMapObj*)(selection)) );
+			((LinkableMapObj*)selection) );
 
 		if (dst &&
 		(typeid(*dst)!=typeid(BranchObj)&&typeid(*dst)!=typeid(MapCenterObj))) 
-		{
 			dst=NULL;
-		}	
 		
 		// Now check, if we have been moving a branch 
 		if (typeid(*selection) == typeid(BranchObj)  )
@@ -3442,13 +3661,13 @@
 			QPoint savePos=QPoint (selection->x(),selection->y() );
 
 			// Reset the temporary drawn link to the original one
-			((LinkableMapObj*)(selection))->unsetParObjTmp();
+			((LinkableMapObj*)selection)->unsetParObjTmp();
 
 
 			copyingObj=false;	
 			if (dst ) 
 			{
-				BranchObj* bs=((BranchObj*)(selection));
+				BranchObj* bs=((BranchObj*)selection);
 				QString undoCom="linkBranchToPos (\""+ 
 					(bs->getParObj())->getSelectString()+
 					"\","+
@@ -3474,7 +3693,11 @@
 						bs->move (savePos);
 				} 
 				saveState (undoCom,bs->getSelectString() );
-			}	
+			} else
+				if (selection->getDepth()==1)
+					// If we have moved mainbranch only save endposition
+					saveState("move "+qpointToString(movingObj_orgPos), selection->getSelectString() );
+			
 			// Draw the original link, before selection was moved around
 			mapCenter->reposition();
 		}
@@ -3646,7 +3869,7 @@
 			BranchObj *bo;
 			for (const char* u=uris.first(); u; u=uris.next())
 			{
-				bo=((BranchObj*)(selection))->addBranch();
+				bo=((BranchObj*)selection)->addBranch();
 				if (bo)
 				{
 					s=QUriDrag::uriToLocalFile(u);
@@ -3688,7 +3911,7 @@
       (typeid(*selection) == typeid(BranchObj)) || 
       (typeid(*selection) == typeid(MapCenterObj))  )
   {
-    BranchObj *bo=((BranchObj*)(selection));
+    BranchObj *bo=((BranchObj*)selection);
     saveState(selection);
     //QString fn=fd->selectedFile();
     //lastImageDir=fn.left(fn.findRev ("/"));
diff -r 2cf3413b6ac9 -r 30b22f7bd009 mapeditor.h
--- a/mapeditor.h	Tue Sep 06 15:04:50 2005 +0000
+++ b/mapeditor.h	Mon Sep 12 19:52:51 2005 +0000
@@ -37,7 +37,8 @@
     void saveState();		// save actual state to backup
     void saveState(LinkableMapObj *);
     void saveState(const QString &, const QString &);
-    void saveState(const SaveMode&, LinkableMapObj *, const QString &, const QString &);
+    void saveState(const QString &, LinkableMapObj *);
+    void saveState(const SaveMode&, const QString &, LinkableMapObj *, const QString &, LinkableMapObj *);
     void parseAtom(const QString &);	
 
     void addFloatImage(const QPixmap &img);
@@ -61,6 +62,7 @@
 	QString getMapName ();	// e.g. "map"
 	QString getDestPath (); // e.g. "/home/tux/map.vym"
     int load (QString&, const LoadMode &);	// newmap, import/replace selection
+public:
     int save(const SaveMode &);	// Save map 
 	void setZipped(bool);		// save map zipped
 	bool saveZipped();			// 1 if file will be saved zipped
@@ -71,12 +73,15 @@
     void exportImage (QString fn);		// export as PNG	
     void exportImage (QString fn, int);	// export in given format
     void exportASCII();
+    void exportLaTeX();
+    void exportOOPresentation();
     void exportXML(const QString&);		// export to directory
     void clear();		// clear map
     void copy();		// copy branch to clipboard
+    void redo();		// redo last action
     void undo();		// undo last action
 private:	
-    void undoXML(const QString &);	// undo by replacing with saved data
+    void undoXML(const QString &, const QString &);
     LinkableMapObj* pasteNoSave();		// paste clipboard to branch
     void cutNoSave();	// cut to clipboard
 public:	
@@ -194,8 +199,6 @@
 	
     LinkableMapObj* selection;		// select a LinkableMapObj
     LinkableMapObj* selectionLast;	// last selection 
-	QString undoSelection;			// selection for undo
-	QString redoSelection;			// selection for redo
     MapObj* movingObj;				// moving a MapObj
 	MapObj* linkingObj_src;			// part of a link
     QPoint movingObj_orgPos;		// org. pos of mouse before move
@@ -208,10 +211,6 @@
     bool mapDefault;				// Flag if map is untouched
     bool mapChanged;				// Flag if undo is possible
 	bool mapUnsaved;				// Flag if map should be saved
-    QString backupXML;				// backup (XML) for undo
-	QString undoCommand;			// FIXME testing
-	QString redoCommand;			// FIXME testing
-									// if != NULL
 
 	bool printFrame;			// Print frame around map
 	bool printFooter;			// Print footer below map
@@ -225,7 +224,10 @@
 	QString lastImageDir;		// save dir for adding images
 
 	bool isInteractive;			// non interactive don't need tmpdirs
-	QString bakMapDir;			// tmp directory with data for undo
+	QString tmpMapDir;			// tmp directory with data for undo/redo
+	int undosTotal;				// total number of undos 
+	int undoNum;				// current number of bakMapDir to be used 
+	int undosAvail;				// how many actions can currently be undone
 	bool blockReposition;		// block while load or undo
 	bool blockSaveState;		// block while load or undo
 
diff -r 2cf3413b6ac9 -r 30b22f7bd009 misc.cpp
--- a/misc.cpp	Tue Sep 06 15:04:50 2005 +0000
+++ b/misc.cpp	Mon Sep 12 19:52:51 2005 +0000
@@ -123,6 +123,45 @@
 	return d;
 }
 
+void removeDir(QDir d)
+{
+	// Traverse directories
+	d.setFilter( QDir::Dirs| QDir::Hidden | QDir::NoSymLinks );
+	const QFileInfoList *dirlist = d.entryInfoList();
+	QFileInfoListIterator itdir( *dirlist );
+	QFileInfo *fi;
+
+	while ( (fi = itdir.current()) != 0 ) 
+	{
+		if (fi->fileName() != "." && fi->fileName() != ".." )
+		{
+			if ( !d.cd(fi->fileName()) ) 
+				qWarning ("removeDir() cannot find the directory "+fi->fileName());
+			else 
+			{
+				// Recursively remove subdirs
+				removeDir (d);
+				d.cdUp();
+			}
+		}	
+		++itdir;
+	}		
+	// Traverse files
+	d.setFilter( QDir::Files| QDir::Hidden | QDir::NoSymLinks );
+	const QFileInfoList *filelist = d.entryInfoList();
+	QFileInfoListIterator itfile( *filelist );
+
+	while ( (fi = itfile.current()) != 0 ) 
+	{
+		QFile (fi->filePath()).remove();
+		
+		++itfile;
+	}	
+
+	if (!d.rmdir(d.path()))
+		qWarning ("removeDir("+d.path()+") failed!");
+}		
+
 // returns masked "<" ">" "&"
 QString quotemeta(const QString &s)
 {
diff -r 2cf3413b6ac9 -r 30b22f7bd009 misc.h
--- a/misc.h	Tue Sep 06 15:04:50 2005 +0000
+++ b/misc.h	Mon Sep 12 19:52:51 2005 +0000
@@ -2,6 +2,7 @@
 #define MISC_H
 
 #include <qpoint.h>
+#include <qdir.h>
 #include <iostream>
 
 using namespace std;
@@ -16,6 +17,7 @@
 QPoint normalise (const QPoint &);
 QString maskPath (QString );
 QString convertToRel (const QString &,const QString &);
+void removeDir(QDir);
 QString quotemeta(const QString&);	
 int max (int,int);
 class BranchObj;
diff -r 2cf3413b6ac9 -r 30b22f7bd009 settings.cpp
--- a/settings.cpp	Tue Sep 06 15:04:50 2005 +0000
+++ b/settings.cpp	Mon Sep 12 19:52:51 2005 +0000
@@ -1,8 +1,145 @@
 #include <iostream>
+#include <qregexp.h>
 #include "settings.h"
-#include "misc.h"
 
 using namespace std;
+
+bool loadStringFromDisk (const QString &fname, QString &s)
+{
+	s="";
+	QFile file ( fname);
+	if ( !file.open( IO_ReadOnly ) ) return false;
+
+	QTextStream ts( &file );
+	ts.setEncoding (QTextStream::UnicodeUTF8);
+	while ( !ts.atEnd() ) 
+		s+=ts.readLine()+"\n"; 
+	file.close();
+	return true;
+}
+
+bool saveStringToDisk (const QString &fname, const QString &s)
+{
+	QFile file( fname);
+
+	file.setName ( fname);
+	if ( !file.open( IO_WriteOnly ) ) 
+	{
+		file.close();
+		return false;
+	}	
+
+	// Write it finally, and write in UTF8, no matter what 
+	QTextStream ts( &file );
+	ts.setEncoding (QTextStream::UnicodeUTF8);
+	ts << s;
+	file.close();
+	return true;
+}
+
+/////////////////////////////////////////////////////////////////
+// SimpleSettings
+/////////////////////////////////////////////////////////////////
+SimpleSettings::SimpleSettings()
+{
+	clear();		 
+}
+
+SimpleSettings::~SimpleSettings()
+{
+}
+
+void SimpleSettings::clear()
+{
+	keylist.clear();
+	valuelist.clear();
+}
+
+void SimpleSettings::readSettings (const QString &path)
+{
+	QString s;
+	if (!loadStringFromDisk(path,s)) 
+	{
+		qWarning ("SimpleSettings::readSettings() Couldn't read "+path);
+		return;
+	}	
+	QStringList lines;
+	lines=QStringList::split (QRegExp("\n"),s,false);
+	int i;
+	QStringList::Iterator it=lines.begin();
+	while (it !=lines.end() )
+	{
+		i=(*it).find("=",0);
+		keylist.append((*it).left(i));
+		valuelist.append((*it).right((*it).length()-i-1));
+		it++;
+	}
+}
+
+void SimpleSettings::writeSettings (const QString &path)
+{
+	QString s;
+	QStringList::Iterator itk=keylist.begin();
+	QStringList::Iterator itv=valuelist.begin();
+
+	// First search for value in settings saved in map
+	while (itk !=keylist.end() )
+	{
+		s+=*itk+"="+*itv+"\n";
+		itk++;
+		itv++;
+	}
+	if (!saveStringToDisk(path,s)) 
+		qWarning ("SimpleSettings::writeSettings() Couldn't write "+path);
+}
+
+QString SimpleSettings::readEntry (const QString &key)
+{
+	QStringList::Iterator itk=keylist.begin();
+	QStringList::Iterator itv=valuelist.begin();
+
+	// First search for value in settings saved in map
+	while (itk !=keylist.end() )
+	{
+		if (*itk == key)
+			return *itv;
+		itk++;
+		itv++;
+	}
+	qWarning ("SimpleSettings::readEntry()  Couldn't find key "+key);
+	return "";
+}
+
+void SimpleSettings::setEntry (const QString &key, const QString &value)
+{
+	QStringList::Iterator itk=keylist.begin();
+	QStringList::Iterator itv=valuelist.begin();
+
+	if (!key.isEmpty() )
+	{
+		// Search for existing entry first
+		while (itk !=keylist.end() )
+		{
+			if (*itk == key)
+			{
+				if (!value.isEmpty())
+					*itv=value;
+				else
+					*itv="";
+				return;
+			}
+			itk++;
+			itv++;
+		}
+		
+		// If no entry exists, append a new one
+		keylist.append (key);
+		valuelist.append (value);
+	}
+}
+
+
+
 /////////////////////////////////////////////////////////////////
 // Settings
 /////////////////////////////////////////////////////////////////
@@ -116,17 +253,3 @@
 	return s;
 }
 
-void Settings::write()
-{
-	QStringList::Iterator itp=pathlist.begin();
-	QStringList::Iterator itk=keylist.begin();
-	QStringList::Iterator itv=valuelist.begin();
-
-	while (itp !=pathlist.end() )
-	{
-		itp++;
-		itk++;
-		itv++;
-	}
-}
-
diff -r 2cf3413b6ac9 -r 30b22f7bd009 settings.h
--- a/settings.h	Tue Sep 06 15:04:50 2005 +0000
+++ b/settings.h	Mon Sep 12 19:52:51 2005 +0000
@@ -7,7 +7,29 @@
 
 #include "misc.h"
 
+// Some helper functions and simplified settings class
+// to read and parse settings e.g.  in undo/redo directories
+bool loadStringFromDisk (const QString &, QString &);
+bool saveStringToDisk (const QString &, const QString &s);
 
+class SimpleSettings
+{
+public:
+    SimpleSettings ();
+	~SimpleSettings ();
+	void clear();
+	void readSettings(const QString &);
+	void writeSettings(const QString &);
+	QString readEntry (const QString &);
+	void setEntry (const QString &,const QString &);
+private:	
+	QStringList keylist;
+	QStringList valuelist;
+};
+
+
+// Overloaded QSettings class, used to save some settings in 
+// a map instead of users home directory
 class Settings:public QSettings,public xmlObj
 {
 public:
@@ -18,7 +40,6 @@
 	QString readLocalEntry ( const QString &, const QString &, const QString &);
 	void setLocalEntry (const QString &, const QString &, const QString &);
 	QString getXMLData (const QString &);
-	void write ();
 
 protected:
 	QStringList pathlist;
diff -r 2cf3413b6ac9 -r 30b22f7bd009 tex/vym.changelog
--- a/tex/vym.changelog	Tue Sep 06 15:04:50 2005 +0000
+++ b/tex/vym.changelog	Mon Sep 12 19:52:51 2005 +0000
@@ -1,3 +1,10 @@
+-------------------------------------------------------------------
+Mon Sep 12 21:39:38 CEST 2005 - uwedr
+
+- Version 1.7.5
+- Feature: Currently 15 levels of undo (GUI to set value still missing)
+- Feature: Experimental LaTeX Export (without headers and opions so far)
+
 -------------------------------------------------------------------
 Sun Sep  5 10:26:15 CEST 2005 - uwedr
 
diff -r 2cf3413b6ac9 -r 30b22f7bd009 version.h
--- a/version.h	Tue Sep 06 15:04:50 2005 +0000
+++ b/version.h	Mon Sep 12 19:52:51 2005 +0000
@@ -1,7 +1,7 @@
 #ifndef VERSION_H 
 #define VERSION_H
 
-#define __VYM_VERSION__ "1.7.4"
-#define __BUILD_DATE__ "September 5, 2005"
+#define __VYM_VERSION__ "1.7.5"
+#define __BUILD_DATE__ "September 12, 2005"
 
 #endif