Index: Scribus/scribus/canvasmode_legacy.cpp
===================================================================
--- Scribus/scribus/canvasmode_legacy.cpp	(wersja 16088)
+++ Scribus/scribus/canvasmode_legacy.cpp	(kopia robocza)
@@ -1800,7 +1800,9 @@
                                                        if (!cc.isNull())
                                                        {
                                                                // K.I.S.S.:
+								currItem->oldCPos = 0;
                                                                currItem->itemText.insertChars(0, cc, true);
+								currItem->asTextFrame()->updateUndo(PageItem::INS,cc);
                                                                if (m_doc->docHyphenator->AutoCheck)
                                                                        m_doc->docHyphenator->slotHyphenate(currItem);
                                                                m_ScMW->BookMarkTxT(currItem);
Index: Scribus/scribus/pageitem.cpp
===================================================================
--- Scribus/scribus/pageitem.cpp	(wersja 16088)
+++ Scribus/scribus/pageitem.cpp	(kopia robocza)
@@ -34,6 +34,9 @@
 #include <QPolygon>
 #include <cassert>
 #include <QDebug>
+#include <iostream>
+#include <sstream>
+#include <string>

 #include "canvas.h"
 #include "scpaths.h"
@@ -44,6 +47,7 @@
 #include "guidemanager.h"
 #include "page.h"
 #include "pageitem_latexframe.h"
+#include "pageitem_textframe.h"
 #include "prefsmanager.h"
 #include "propertiespalette.h"
 #include "resourcecollection.h"
@@ -60,9 +64,11 @@
 #include "scribusstructs.h"
 #include "scribuswin.h"
 #include "sctextstream.h"
+#include "serializer.h"
 #include "selection.h"
 #include "sclimits.h"
 #include "text/nlsconfig.h"
+#include "desaxe/saxXML.h"
 #include "undomanager.h"
 #include "undostate.h"
 #include "util.h"
@@ -327,6 +333,7 @@
        CurX = 0;
        CurY = 0;
        CPos = 0;
+	oldCPos = 0;
        Extra = 0;
        TExtra = 0;
        BExtra = 0;
@@ -3209,6 +3216,9 @@
                        restoreShapeContour(ss, isUndo);
                else if (ss->contains("APPLY_IMAGE_EFFECTS"))
                        restoreImageEffects(ss, isUndo);
+		else if (ss->contains("STEXT"))
+			restoreEditText(ss, isUndo);
+
        }
        if (!OnMasterPage.isEmpty())
                m_Doc->setCurrentPage(oldCurrentPage);
@@ -3707,8 +3717,190 @@
        }
 }

+void PageItem::restoreEditText(SimpleState *state, bool isUndo)
+{
+	if (!isTextFrame())
+		return;
+	EditAct action = (EditAct) state->getInt("STEXT");
+	if (action == PARAMFULL || action == PARAMSEL)
+	{
+		QString buffer;
+		if (isUndo)
+			buffer.append(state->get("STEXT_OLD"));
+		else
+			buffer.append(state->get("STEXT_NEW"));
+		if (!buffer.isEmpty())
+		{
+			Serializer dig(*m_Doc);
+			dig.store<ScribusDoc>("<scribusdoc>", m_Doc);
+			StoryText::desaxeRules("/", dig, "SCRIBUSTEXT");
+			dig.addRule("/SCRIBUSTEXT", desaxe::Result<StoryText>());
+			dig.parseMemory(buffer.toStdString().c_str(), buffer.length());
+			StoryText* story = dig.result<StoryText>();
+			if (action == PARAMFULL)
+			{
+				itemText.selectAll();
+				itemText.clear();
+				itemText.append(*story);
+			}
+			else if (action == PARAMSEL)
+			{
+				itemText.deselectAll();
+				itemText.select(state->getInt("STEXT_SELSTART"),state->getInt("STEXT_SELLEN"));
+				asTextFrame()->deleteSelectedTextFromFrame();
+				itemText.insert(state->getInt("STEXT_SELSTART"), *story);
+				itemText.select(state->getInt("STEXT_SELSTART"), story->length());
+				HasSel = true;
+			}
+			CPos = itemText.endOfSelection();
+			delete story;
+		}
+		else { qDebug() << "UNDO buffer EMPTY";}
+	}
+	else if (action == REPSAX)
+	{
+		QString buffout, buffin;  //buffout is deleted, buffin is inserted
+		int pos = state->getInt("STEXT_CPOS");
+		if (isUndo)
+		{
+			buffin.append(state->get("STEXT_OLD"));
+			buffout.append(state->get("STEXT_NEW"));
+		}
+		else
+		{
+			buffin.append(state->get("STEXT_NEW"));
+			buffout.append(state->get("STEXT_OLD"));
+		}
+
+		Serializer dig(*m_Doc);
+		dig.store<ScribusDoc>("<scribusdoc>", m_Doc);
+		StoryText::desaxeRules("/", dig, "SCRIBUSTEXT");
+		dig.addRule("/SCRIBUSTEXT", desaxe::Result<StoryText>());
+		dig.parseMemory(buffout.toStdString().c_str(), buffout.length());
+		StoryText* story = dig.result<StoryText>();
+		itemText.select(pos,story->length(), true);
+		asTextFrame()->deleteSelectedTextFromFrame();
+
+		Serializer dig2(*m_Doc);
+		dig2.store<ScribusDoc>("<scribusdoc>", m_Doc);
+		StoryText::desaxeRules("/", dig2, "SCRIBUSTEXT");
+		dig2.addRule("/SCRIBUSTEXT", desaxe::Result<StoryText>());
+		dig2.parseMemory(buffin.toStdString().c_str(), buffin.length());
+		story = dig2.result<StoryText>();
+		itemText.insert(pos,*story);
+		itemText.select(pos, story->length());
+		HasSel = true;
+		CPos = pos + story->length();
+		delete story;
+	}
+	else if (action == INSSAX || action == DELSAX)
+	{
+		QString str = state->get("STEXT_STR");
+		if (str.isEmpty())
+			str = itemTextSaxed;
+		int pos = state->getInt("STEXT_CPOS");
+		Serializer dig(*m_Doc);
+		dig.store<ScribusDoc>("<scribusdoc>", m_Doc);
+		StoryText::desaxeRules("/", dig, "SCRIBUSTEXT");
+		dig.addRule("/SCRIBUSTEXT", desaxe::Result<StoryText>());
+		dig.parseMemory(str.toStdString().c_str(), str.length());
+		StoryText* story = dig.result<StoryText>();
+		if ((action == INSSAX && isUndo) || (action == DELSAX && !isUndo))
+		{
+			//undo for INSSAX, redo for DELSAX
+			itemText.select(pos, story->length());
+			asTextFrame()->deleteSelectedTextFromFrame();
+		}
+		else
+		{
+			//undo for DELSAX, redo for INSSAX
+			itemText.insert(pos, *story);
+			CPos = pos + story->length();
+		}
+		delete story;
+	}
+	else if (action == INS)
+	{
+		QString str = state->get("STEXT_STR");
+		int pos = state->getInt("STEXT_CPOS");
+		if (isUndo)
+		{
+			itemText.select(pos, str.length());
+			asTextFrame()->deleteSelectedTextFromFrame();
+		}
+		else
+		{
+			itemText.insertChars(pos, str, true);
+			CPos = pos + str.length();
+		}
+	}
+	// after Undo or Redo new actions should create new undoStates
+	asTextFrame()->lastUndoAction = NOACTION;
+
+	m_Doc->scMW()->setTBvals(this);
+	update();
+}
+
+QString PageItem::getItemTextSaxed(EditActPlace undoItem)
+{
+	if (!isTextFrame()) return "";
+	StoryText iT(m_Doc);
+	iT.setDefaultStyle(itemText.defaultStyle());
+	if (undoItem == FRAME)
+		iT.insert(0, itemText);
+	else
+	{
+		int StartOldSel = 0, LenOldSel = 0;
+		if (undoItem == PARAGRAPH)
+		{
+			if (HasSel)
+			{
+				StartOldSel = itemText.startOfSelection();
+				LenOldSel = itemText.lengthOfSelection();
+			}
+			asTextFrame()->ExpandParSel();
+		}
+		else if (undoItem == CHAR || (undoItem == SELECTION && !HasSel))
+		{
+			itemText.select(CPos,1);
+			HasSel = true;
+		}
+		//is SELECTION
+		iT.insert(0, itemText, true);
+		if (LenOldSel > 0) //restoring old selection if undoItem was PARAPGRAPH
+		{
+			itemText.select(StartOldSel, LenOldSel);
+			HasSel = true;
+		}
+	}
+	//saxing text
+	std::ostringstream xmlString;
+	SaxXML xmlStream(xmlString);
+	xmlStream.beginDoc();
+	iT.saxx(xmlStream, "SCRIBUSTEXT");
+	xmlStream.endDoc();
+	std::string xml(xmlString.str());
+	return QString(xml.c_str());
+}
+
+QString PageItem::getTextSaxed(QString str)
+{
+	StoryText iT(m_Doc);
+	iT.setDefaultStyle(itemText.defaultStyle());
+	iT.insertChars(0,str,true);
+	std::ostringstream xmlString;
+	SaxXML xmlStream(xmlString);
+	xmlStream.beginDoc();
+	iT.saxx(xmlStream, "SCRIBUSTEXT");
+	xmlStream.endDoc();
+	std::string xml(xmlString.str());
+	return QString(xml.c_str());
+}
+
 void PageItem::select()
 {
+	if (m_Doc->m_Selection->count() == 1 && m_Doc->m_Selection->itemAt()->isTextFrame())
+		m_Doc->m_Selection->itemAt()->asTextFrame()->lastUndoAction = PageItem::NOACTION;
        m_Doc->view()->Deselect(false);
        //CB #2969 add this true parm to addItem so we dont connectToGUI, the rest of view->SelectItem isnt needed anyway
        m_Doc->m_Selection->addItem(this, true);
Index: Scribus/scribus/pageitem_textframe.cpp
===================================================================
--- Scribus/scribus/pageitem_textframe.cpp	(wersja 16160)
+++ Scribus/scribus/pageitem_textframe.cpp	(kopia robocza)
@@ -46,6 +46,8 @@
 #include "scribus.h"
 #include "scribusdoc.h"
 #include "scribusstructs.h"
+#include "scribusXml.h"
+#include "serializer.h"
 #include "selection.h"
 #include "text/nlsconfig.h"
 #include "undomanager.h"
@@ -67,6 +69,8 @@
        unicodeTextEditMode = false;
        unicodeInputCount = 0;
        unicodeInputString = "";
+	lastUndoAction = NOACTION;
+//	lastAction4Paragraph = false;

        connect(&itemText,SIGNAL(changed()), this, SLOT(slotInvalidateLayout()));
 }
@@ -78,7 +82,9 @@
        unicodeTextEditMode = false;
        unicodeInputCount = 0;
        unicodeInputString = "";
-
+	lastUndoAction = NOACTION;
+//	lastAction4Paragraph = false;
+
        connect(&itemText,SIGNAL(changed()), this, SLOT(slotInvalidateLayout()));
 }

@@ -2653,11 +2676,11 @@
        PageItem *nextItem = this;
        while (nextItem->prevInChain() != 0)
                nextItem = nextItem->prevInChain();
-
+	nextItem->itemTextSaxed = nextItem->getItemTextSaxed(PageItem::FRAME); //for undo
        ParagraphStyle defaultStyle = nextItem->itemText.defaultStyle();
        nextItem->itemText.clear();
        nextItem->itemText.setDefaultStyle(defaultStyle);
-
+	nextItem->asTextFrame()->updateUndo(); //for undo
        while (nextItem != 0)
        {
                nextItem->CPos = 0;
@@ -2710,6 +2733,7 @@
        case Qt::Key_Down:
                if ( (buttonModifiers & Qt::ShiftModifier) == 0 )
                        deselectAll();
+		lastUndoAction = PageItem::NOACTION;
        }

        if (unicodeTextEditMode)
@@ -2735,11 +2759,25 @@
                        if (ok)
                        {
                                if (itemText.lengthOfSelection() > 0)
+				{
+					itemTextSaxed = getItemTextSaxed(PageItem::SELECTION);
                                        deleteSelectedTextFromFrame();
+					lastUndoAction = PageItem::NOACTION;
+				}
                                if (conv < 31)
                                        conv = 32;
+				if (conv == 32)
+				{
+					qDebug() << "SPACE conv?";
+					lastUndoAction = PageItem::NOACTION;
+				}
+				oldCPos = CPos;
                                itemText.insertChars(CPos, QString(QChar(conv)), true);
                                CPos += 1;
+				if (itemTextSaxed.isEmpty())
+					updateUndo(INS, QString(QChar(conv)));
+				else
+					updateUndo(REPSAX, getTextSaxed(QString(QChar(conv))));
 //				Tinput = true;
                                m_Doc->scMW()->setTBvals(this);
                                update();
@@ -3016,7 +3054,10 @@
                {
                        if (itemText.lengthOfSelection() > 0)
                        {
+				oldCPos = itemText.startOfSelection();
+				itemTextSaxed = getItemTextSaxed(PageItem::SELECTION);
                                deleteSelectedTextFromFrame();
+				updateUndo(DELSAX);
                                m_Doc->scMW()->setTBvals(this);
                                update();
 //				view->RefreshItem(this);
@@ -3031,8 +3072,14 @@
                }
                cr = itemText.text(CPos,1);
                if (itemText.lengthOfSelection() == 0)
+		{
                        itemText.select(CPos, 1, true);
+			HasSel = true;
+		}
+		oldCPos = itemText.startOfSelection();
+		itemTextSaxed = getItemTextSaxed(PageItem::SELECTION);
                deleteSelectedTextFromFrame();
+		updateUndo(DELSAX);
                update();
 //		Tinput = false;
                if ((cr == QChar(13)) && (itemText.length() != 0))
@@ -3048,7 +3095,10 @@
                {
                        if (itemText.lengthOfSelection() > 0)
                        {
+				oldCPos = itemText.startOfSelection();
+				itemTextSaxed = getItemTextSaxed(PageItem::SELECTION);
                                deleteSelectedTextFromFrame();
+				updateUndo(DELSAX);
                                m_Doc->scMW()->setTBvals(this);
                                update();
                        }
@@ -3061,8 +3111,12 @@
                {
                        --CPos;
                        itemText.select(CPos, 1, true);
+			HasSel = true;
                }
+		oldCPos = itemText.startOfSelection();
+		itemTextSaxed = getItemTextSaxed(PageItem::SELECTION);
                deleteSelectedTextFromFrame();
+		updateUndo(DELSAX);
 //		Tinput = false;
                if ((cr == QChar(13)) && (itemText.length() != 0))
                {
@@ -3090,7 +3144,10 @@
 #endif
                        if (!controlCharHack && !x11Hack && !k->text().isEmpty())
                        {
+				oldCPos = itemText.startOfSelection();
+				itemTextSaxed = getItemTextSaxed(PageItem::SELECTION);
                                deleteSelectedTextFromFrame();
+				lastUndoAction = PageItem::NOACTION;
                                doUpdate = true;
                        }
                        /*
@@ -3106,16 +3163,30 @@
                //if ((kk == Qt::Key_Tab) || ((kk == Qt::Key_Return) && (buttonState & Qt::ShiftButton)))
                if (kk == Qt::Key_Tab)
                {
+			oldCPos = CPos;
                        itemText.insertChars(CPos, QString(SpecialChars::TAB), true);
                        CPos += 1;
+			lastUndoAction = PageItem::NOACTION;
+			if (itemTextSaxed.isEmpty())
+				updateUndo(INS, QString(SpecialChars::TAB));
+			else
+				updateUndo(REPSAX, getTextSaxed(QString(SpecialChars::TAB)));
 //			Tinput = true;
 //			view->RefreshItem(this);
                        doUpdate = true;
                }
                else if ((uc[0] > QChar(31) && m_Doc->currentStyle.charStyle().font().canRender(uc[0])) || (as == 13) || (as == 30))
                {
+			if (uc[0] == QChar(32) || uc[0] == QChar(13))
+				lastUndoAction = PageItem::NOACTION;
+			if (lastUndoAction != PageItem::INS)
+				oldCPos = CPos;
                        itemText.insertChars(CPos, uc, true);
                        CPos += 1;
+			if (itemTextSaxed.isEmpty())
+				updateUndo(INS, uc);
+			else
+				updateUndo(REPSAX, getTextSaxed(uc));
                        if ((m_Doc->docHyphenator->AutoCheck) && (CPos > 1))
                        {
                                Twort = "";
@@ -3278,8 +3348,30 @@
 // 	layoutWeakLock = true;
 // 	update();
        m_Doc->regionsChanged()->update(getBoundingRect());
+	lastUndoAction = PageItem::NOACTION;
 }

+void PageItem_TextFrame::ExpandParSel() //expand selection to whole paragrpah(s)
+{
+	if (m_Doc->appMode != modeEdit)
+		return;
+	int StartSel = 0, LenSel = 0;
+	if (HasSel)
+	{
+		//extend selection to whole paragraphs
+		StartSel = itemText.startOfParagraph(itemText.nrOfParagraph(itemText.startOfSelection()));
+		LenSel = itemText.endOfParagraph(itemText.nrOfParagraph(itemText.endOfSelection())) - StartSel;
+	}
+	else
+	{
+		//extend selection to whole paragraph
+		StartSel = itemText.startOfParagraph(itemText.nrOfParagraph(CPos));
+		LenSel = itemText.endOfParagraph(itemText.nrOfParagraph(CPos)) - StartSel;
+	}
+	itemText.select(StartSel, LenSel);
+	qDebug() << "ExpandParSel" << StartSel << LenSel;
+}
+
 void PageItem_TextFrame::deselectAll()
 {
        if ( itemText.lengthOfSelection() > 0 )
@@ -3299,6 +3391,7 @@
        }
        //CB Replace with direct call for now //emit HasNoTextSel();
        m_Doc->scMW()->DisableTxEdit();
+	lastUndoAction = PageItem::NOACTION;
 }

 double PageItem_TextFrame::columnWidth()
@@ -3558,3 +3651,75 @@
 {
 	invalidateLayout();
 }
+
+void PageItem_TextFrame::updateUndo(EditAct action, QString str)
+{
+	if (UndoManager::undoEnabled() && undoManager->undoEnabled())
+	{
+		SimpleState* ss;
+		bool newState = true;  // indicate when new undoState should be created
+		if (lastUndoAction == action && action != REPSAX && action != DELSAX)
+		{
+			ss = (SimpleState*) undoManager->getLastUndoState();
+			if (ss->undoObject() == this)
+			{
+				if (action == PARAMFULL || action == PARAMSEL)
+				{
+					itemTextSaxed = ss->get("STEXT_OLD");
+					newState = false;
+				}
+				else if (action == INSSAX || action == INS)
+				{
+					QString tmpstr(ss->get("STEXT_STR"));
+					tmpstr.append(str);
+					str = tmpstr;
+					newState = false;
+				}
+			}
+		}
+		if (newState)
+		{
+			ss = new SimpleState(UndoManager::EditText);
+			ss->set("STEXT_CPOS",oldCPos);
+		}
+		if (action == INSSAX || action == INS)
+			ss->set("STEXT_STR",str);
+		else if (action == DELSAX)
+			ss->set("STEXT_STR",itemTextSaxed);
+		else if (action == REPSAX)
+		{
+			ss->set("STEXT_NEW",str);
+			ss->set("STEXT_OLD",itemTextSaxed);
+		}
+		else
+		{
+			if (action == PARAMFULL && m_Doc->appMode == modeEdit)
+			{
+				//action is for paragraph where cursor is
+				ExpandParSel();
+				action = PARAMSEL;
+			}
+			if (action == PARAMSEL)
+			{
+				ss->set("STEXT_CPOS",CPos);
+				ss->set("STEXT_SELSTART", itemText.startOfSelection());
+				ss->set("STEXT_SELLEN", itemText.endOfSelection() - itemText.startOfSelection());
+			}
+			ss->set("STEXT_OLD", itemTextSaxed);
+			itemTextSaxed = getItemTextSaxed((action == PARAMSEL) ? SELECTION : FRAME);
+			ss->set("STEXT_NEW", itemTextSaxed);
+			if (QString::compare(ss->get("STEXT_OLD"),ss->get("STEXT_NEW")) == 0)
+			{
+				//nothing change - quit without set new Undo step
+				itemTextSaxed.clear();
+				delete ss;
+				return;
+			}
+		}
+		itemTextSaxed.clear();
+		lastUndoAction = action;
+		ss->set("STEXT",(int) action);
+		if (newState)
+			undoManager->action(this, ss);
+	}
+}
Index: Scribus/scribus/scribus.cpp
===================================================================
--- Scribus/scribus/scribus.cpp	(wersja 16088)
+++ Scribus/scribus/scribus.cpp	(kopia robocza)
@@ -137,6 +137,7 @@
 #include "nodeeditpalette.h"
 #include "outlinepalette.h"
 #include "page.h"
+#include "pageitem.h"
 #include "pageitem_imageframe.h"
 #include "pageitem_latexframe.h"
 #include "pageitem_textframe.h"
@@ -1112,9 +1120,18 @@
                                        if (unicodevalue!=-1)
                                        {
                                                if (currItem->HasSel && currItem->itemType()==PageItem::TextFrame)
+						{
+							currItem->oldCPos = currItem->itemText.startOfSelection();
+							currItem->itemTextSaxed = currItem->getItemTextSaxed(PageItem::SELECTION);
                                                        currItem->asTextFrame()->deleteSelectedTextFromFrame();
-
+						}
+						else
+							currItem->oldCPos = currItem->CPos;
                                                currItem->itemText.insertChars(currItem->CPos, QString(QChar(unicodevalue)), true);
+						if (currItem->itemTextSaxed.isEmpty())
+							currItem->asTextFrame()->updateUndo(PageItem::INS, QString(QChar(unicodevalue)));
+						else
+							currItem->asTextFrame()->updateUndo(PageItem::REPSAX, currItem->getTextSaxed(QString(QChar(unicodevalue))));
                                                currItem->CPos += 1;
 //						currItem->Tinput = true;
                                                currItem->update();
@@ -1131,7 +1148,9 @@
                                                        currItem->itemText.item(qMax(currItem->CPos-1,0))->setEffects(fl);
 #else
                                                        currItem->itemText.insertChars(currItem->CPos, QString(SpecialChars::SHYPHEN), true);
+							currItem->oldCPos = currItem->CPos;
                                                        currItem->CPos += 1;
+							currItem->asTextFrame()->updateUndo(PageItem::INS, QString(SpecialChars::SHYPHEN));
 #endif
 //							currItem->Tinput = true;
                                                        currItem->update();
@@ -3318,7 +3337,6 @@
                scrActions["itemLockSize"]->setChecked(currItem->sizeLocked());
                scrActions["itemPrintingEnabled"]->setChecked(currItem->printEnabled());
        }
-
        //propertiesPalette->NewSel(SelectedType);
        if (SelectedType != -1)
        {
@@ -4289,6 +4307,7 @@
                        ImportSetup impsetup=gt->run();
                        if (impsetup.runDialog)
                        {
+				currItem->itemTextSaxed = currItem->getItemTextSaxed(PageItem::FRAME);
                                if (currItem->itemText.length() != 0)
                                {
                                        int t = QMessageBox::warning(this, CommonStrings::trWarning, tr("Do you really want to clear all your text?"), QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
@@ -4296,6 +4315,7 @@
                                                return;
                                }
                                gt->launchImporter(impsetup.importer, impsetup.filename, impsetup.textOnly, impsetup.encoding, false);
+				currItem->asTextFrame()->updateUndo();
                        }
                        delete gt;
                        if (doc->docHyphenator->AutoCheck)
@@ -4321,7 +4341,8 @@

        if (!currItem->asTextFrame())
                return; // not a text frame
-
+	// I dont know what is doing here, but Undo dont hurts
+	currItem->itemTextSaxed = currItem->getItemTextSaxed(PageItem::FRAME);
        ScGTPluginManager::instance()->run();
        if (doc->docHyphenator->AutoCheck)
                doc->docHyphenator->slotHyphenate(currItem);
@@ -4330,6 +4351,7 @@
                if (doc->Items->at(a)->isBookmark)
                        bookmarkPalette->BView->ChangeText(doc->Items->at(a));
        }
+	currItem->asTextFrame()->updateUndo();
        view->DrawNew();
        slotDocCh();
 }
@@ -4385,7 +4407,10 @@
                ImportSetup impsetup=gt->run();
                if (impsetup.runDialog)
                {
+			PageItem *currItem = doc->m_Selection->itemAt(0);
+			currItem->itemTextSaxed = currItem->getItemTextSaxed(PageItem::FRAME);
                        gt->launchImporter(impsetup.importer, impsetup.filename, impsetup.textOnly, impsetup.encoding, true);
+			currItem->asTextFrame()->updateUndo();
                }
                delete gt;
                //CB Hyphenating now emits doc changed, plus we change lang as appropriate
@@ -4964,6 +4989,10 @@
                {
                        if ((currItem->itemText.length() == 0) || (!currItem->HasSel))
                                return;
+			currItem->oldCPos = currItem->itemText.startOfSelection();
+			//for undo
+			currItem->itemTextSaxed = currItem->getItemTextSaxed(PageItem::SELECTION);
+
                        StoryText itemText(doc);
                        itemText.setDefaultStyle(currItem->itemText.defaultStyle());
                        itemText.insert(0, currItem->itemText, true);
@@ -4981,6 +5010,8 @@
                        QApplication::clipboard()->setMimeData(mimeData, QClipboard::Clipboard);

                        dynamic_cast<PageItem_TextFrame*>(currItem)->deleteSelectedTextFromFrame();
+			//for undo
+			currItem->asTextFrame()->updateUndo(PageItem::DELSAX);
                        currItem->update();
                }
                else
@@ -5116,14 +5147,19 @@
                {
                        PageItem_TextFrame *currItem = dynamic_cast<PageItem_TextFrame*>(doc->m_Selection->itemAt(0));
                        assert(currItem != NULL);
+			currItem->lastUndoAction = PageItem::NOACTION;
                        if (currItem->HasSel)
+			{
+				//for text undo, storing current selection
+				currItem->itemTextSaxed = currItem->getItemTextSaxed(PageItem::SELECTION);
                                currItem->deleteSelectedTextFromFrame();
+			}

                        if (currItem->CPos < 0)
                                currItem->CPos = 0;
                        if (currItem->CPos > currItem->itemText.length())
                                currItem->CPos = currItem->itemText.length();
-
+			currItem->oldCPos = currItem->CPos;
                        if (ScMimeData::clipboardHasScribusText())
                        {
                                Serializer dig(*doc);
@@ -5137,6 +5173,13 @@
                                StoryText* story = dig.result<StoryText>();

                                currItem->itemText.insert(currItem->CPos, *story);
+
+				//for text undo, select inserted text for saxing it
+				currItem->itemText.select(currItem->CPos,story->length());
+				currItem->HasSel = true;
+				//if itemTextSaxed is not empty there was selection
+				currItem->updateUndo(currItem->itemTextSaxed.isEmpty() ? PageItem::INSSAX : PageItem::REPSAX,currItem->getItemTextSaxed(PageItem::SELECTION));
+
                                currItem->CPos += story->length();

                                delete story;
@@ -5222,6 +5265,11 @@
                                currItem->itemText.insertObject(currItem->CPos, currItem3);
                                currItem->CPos += 1;
                                undoManager->setUndoEnabled(true);
+				//for text undo, select inserted text for saxing it
+				currItem->itemText.select(currItem->oldCPos,currItem->CPos - currItem->oldCPos);
+				currItem->HasSel = true;
+				//if itemTextSaxed is not empty there was selection
+				currItem->updateUndo(currItem->itemTextSaxed.isEmpty() ? PageItem::INSSAX : PageItem::REPSAX,currItem->getItemTextSaxed(PageItem::SELECTION));
                        }
                        else
                        {
@@ -5230,6 +5278,15 @@
                                text = text.replace("\r\n", SpecialChars::PARSEP);
                                text = text.replace('\n', SpecialChars::PARSEP);
                                currItem->itemText.insertChars(currItem->CPos, text, true);
+				//for text undo, select inserted text for saxing it
+				currItem->itemText.select(currItem->CPos,text.length());
+				currItem->HasSel = true;
+				//if itemTextSaxed is not empty there was selection
+				if (currItem->itemTextSaxed.isEmpty())
+					currItem->updateUndo(PageItem::INS, text);
+				else
+					currItem->updateUndo(PageItem::REPSAX, currItem->getTextSaxed(text));
+
                        }
                        currItem->update();
                }
@@ -6927,7 +6984,15 @@
                        }
                }
        }
+	//for undo
+	PageItem *currItem = doc->m_Selection->itemAt(0);
+	if (currItem->asTextFrame())
+		currItem->itemTextSaxed = currItem->getItemTextSaxed(doc->appMode == modeEdit? PageItem::SELECTION : PageItem::FRAME);
+	qDebug() << "setNewFont" << currItem->HasSel;
        doc->itemSelection_SetFont(nf2);
+	if (currItem->asTextFrame())
+		currItem->asTextFrame()->updateUndo(currItem->HasSel? PageItem::PARAMSEL : PageItem::PARAMFULL);
+
 //	doc->currentStyle.charStyle().setFont((*doc->AllFonts)[nf2]);
        view->DrawNew();
 // 	slotDocCh();
@@ -6935,6 +7000,10 @@

 void ScribusMainWindow::setItemFSize(int id)
 {
+	PageItem *currItem = doc->m_Selection->itemAt(0);
+	if (currItem->asTextFrame())
+		currItem->itemTextSaxed = currItem->getItemTextSaxed(doc->appMode == modeEdit? PageItem::SELECTION : PageItem::FRAME);
+
        int c = id;
        if (c != -1)
                doc->itemSelection_SetFontSize(c*10);
@@ -6950,6 +7019,9 @@
                }
                delete dia;
        }
+	if (currItem->asTextFrame())
+		currItem->asTextFrame()->updateUndo(currItem->HasSel? PageItem::PARAMSEL : PageItem::PARAMFULL);
+
        propertiesPalette->setSize(c*10);
 // 	slotDocCh();
 }
@@ -7330,9 +7402,9 @@
        if (HaveDoc)
        {
 //		doc->currentStyle.setAlignment(static_cast<ParagraphStyle::AlignmentType>(a));
+		PageItem *currItem = doc->m_Selection->itemAt(0);
                doc->itemSelection_SetAlignment(a);
                propertiesPalette->setAli(a);
-		PageItem *currItem = doc->m_Selection->itemAt(0);
                setTBvals(currItem);
        }
 }
@@ -7347,8 +7419,16 @@
                        doc->itemSelection_EraseParagraphStyle();
                }
                else */
-			doc->itemSelection_SetNamedParagraphStyle(name);
                PageItem *currItem = doc->m_Selection->itemAt(0);
+		if (currItem->asTextFrame())
+		{
+//			currItem->asTextFrame()->ExpandParSel();
+//			currItem->asTextFrame()->lastAction4Paragraph = true;
+			currItem->itemTextSaxed = currItem->getItemTextSaxed(doc->appMode == modeEdit? PageItem::PARAGRAPH : PageItem::FRAME);
+		}
+		doc->itemSelection_SetNamedParagraphStyle(name);
+		if (currItem->asTextFrame())
+			currItem->asTextFrame()->updateUndo();
                setTBvals(currItem);
        }
 }
@@ -7363,8 +7443,12 @@
                        doc->itemSelection_EraseCharStyle();
                }
                else */
-			doc->itemSelection_SetNamedCharStyle(name);
                PageItem *currItem = doc->m_Selection->itemAt(0);
+		if (currItem->asTextFrame())
+			currItem->itemTextSaxed = currItem->getItemTextSaxed(doc->appMode == modeEdit? PageItem::SELECTION : PageItem::FRAME);
+		doc->itemSelection_SetNamedCharStyle(name);
+		if (currItem->asTextFrame())
+			currItem->asTextFrame()->updateUndo(currItem->HasSel? PageItem::PARAMSEL : PageItem::PARAMFULL);
                setTBvals(currItem);
        }
 }
Index: Scribus/scribus/propertiespalette.cpp
===================================================================
--- Scribus/scribus/propertiespalette.cpp	(wersja 16088)
+++ Scribus/scribus/propertiespalette.cpp	(kopia robocza)
@@ -52,7 +52,9 @@
 #include "colorlistbox.h"
 #include "sccolorengine.h"
 #include "cpalette.h"
+#include "pageitem.h"
 #include "pageitem_textframe.h"
+#include "styles/paragraphstyle.h"
 #include "sccombobox.h"
 #include "scfonts.h"
 #include "scribus.h"
@@ -2923,8 +2936,16 @@
 {
        if ((HaveDoc) && (HaveItem))
        {
+		if (CurItem->asTextFrame())
+		{
+//			CurItem->asTextFrame()->ExpandParSel();
+			CurItem->itemTextSaxed = CurItem->getItemTextSaxed(doc->appMode == modeEdit? PageItem::PARAGRAPH : PageItem::FRAME);
+//			CurItem->asTextFrame()->lastAction4Paragraph = true;
+		}
                doc->itemSelection_SetLineSpacingMode(id);
                updateStyle(doc->appMode == modeEdit? CurItem->currentStyle() : CurItem->itemText.defaultStyle());
+		if (CurItem->asTextFrame())
+			CurItem->asTextFrame()->updateUndo();
        }
 }

@@ -3266,6 +3285,8 @@
 {
        if (!HaveDoc || !HaveItem || !m_ScMW || m_ScMW->scriptIsRunning())
                return;
+	if (CurItem->asTextFrame())
+		CurItem->itemTextSaxed = CurItem->getItemTextSaxed(PageItem::FRAME);
        int omt(ParagraphStyle::OM_None);
 //	if (optMarginCheckLeftProtruding->isChecked()) omt+=ParagraphStyle::OM_LeftProtruding;
        if (optMarginRadioBoth->isChecked())
@@ -3276,6 +3297,8 @@
                omt = ParagraphStyle::OM_RightHangingPunct;

        doc->itemSelection_SetOpticalMargins(omt);
+	if (CurItem->asTextFrame())
+		CurItem->asTextFrame()->updateUndo();
 }

 void PropertiesPalette::resetOpticalMargins()
@@ -3303,9 +3326,13 @@
 {
        if (!HaveDoc || !HaveItem || !m_ScMW || m_ScMW->scriptIsRunning())
                return;
+	if (CurItem->asTextFrame())
+		CurItem->itemTextSaxed = CurItem->getItemTextSaxed(doc->appMode == modeEdit? PageItem::SELECTION : PageItem::FRAME);
        ParagraphStyle newStyle;
        newStyle.setMinWordTracking(minWordTrackingSpinBox->value() / 100.0);
        doc->itemSelection_ApplyParagraphStyle(newStyle);
+	if (CurItem->asTextFrame())
+		CurItem->asTextFrame()->updateUndo(CurItem->HasSel? PageItem::PARAMSEL : PageItem::PARAMFULL);
 }


@@ -3313,28 +3340,40 @@
 {
        if (!HaveDoc || !HaveItem || !m_ScMW || m_ScMW->scriptIsRunning())
                return;
+	if (CurItem->asTextFrame())
+		CurItem->itemTextSaxed = CurItem->getItemTextSaxed(doc->appMode == modeEdit? PageItem::SELECTION : PageItem::FRAME);
        ParagraphStyle newStyle;
 //	newStyle.setNormWordTracking(percent / 100.0);
        newStyle.charStyle().setWordTracking(normWordTrackingSpinBox->value() / 100.0);
        doc->itemSelection_ApplyParagraphStyle(newStyle);
+	if (CurItem->asTextFrame())
+		CurItem->asTextFrame()->updateUndo(CurItem->HasSel? PageItem::PARAMSEL : PageItem::PARAMFULL);
 }

 void PropertiesPalette::setMinGlyphExtension()
 {
        if (!HaveDoc || !HaveItem || !m_ScMW || m_ScMW->scriptIsRunning())
                return;
+	if (CurItem->asTextFrame())
+		CurItem->itemTextSaxed = CurItem->getItemTextSaxed(doc->appMode == modeEdit? PageItem::SELECTION : PageItem::FRAME);
        ParagraphStyle newStyle;
        newStyle.setMinGlyphExtension(minGlyphExtSpinBox->value() / 100.0);
        doc->itemSelection_ApplyParagraphStyle(newStyle);
+	if (CurItem->asTextFrame())
+		CurItem->asTextFrame()->updateUndo(CurItem->HasSel? PageItem::PARAMSEL : PageItem::PARAMFULL);
 }

 void PropertiesPalette::setMaxGlyphExtension()
 {
        if (!HaveDoc || !HaveItem || !m_ScMW || m_ScMW->scriptIsRunning())
                return;
+	if (CurItem->asTextFrame())
+		CurItem->itemTextSaxed = CurItem->getItemTextSaxed(doc->appMode == modeEdit? PageItem::SELECTION : PageItem::FRAME);
        ParagraphStyle newStyle;
        newStyle.setMaxGlyphExtension(maxGlyphExtSpinBox->value() / 100.0);
        doc->itemSelection_ApplyParagraphStyle(newStyle);
+	if (CurItem->asTextFrame())
+		CurItem->asTextFrame()->updateUndo(CurItem->HasSel? PageItem::PARAMSEL : PageItem::PARAMFULL);
 }


@@ -3352,14 +3391,22 @@
 {
        if (!HaveDoc || !HaveItem || !m_ScMW || m_ScMW->scriptIsRunning())
                return;
+	if (CurItem->asTextFrame())
+		CurItem->itemTextSaxed = CurItem->getItemTextSaxed(doc->appMode == modeEdit? PageItem::SELECTION : PageItem::FRAME);
        doc->itemSelection_SetScaleV(qRound(ChScaleV->value() * 10));
+	if (CurItem->asTextFrame())
+		CurItem->asTextFrame()->updateUndo(CurItem->HasSel? PageItem::PARAMSEL : PageItem::PARAMFULL);
 }

 void PropertiesPalette::NewTBase()
 {
        if (!HaveDoc || !HaveItem || !m_ScMW || m_ScMW->scriptIsRunning())
                return;
+	if (CurItem->asTextFrame())
+		CurItem->itemTextSaxed = CurItem->getItemTextSaxed(doc->appMode == modeEdit? PageItem::SELECTION : PageItem::FRAME);
        doc->itemSelection_SetBaselineOffset(qRound(ChBase->value() * 10));
+	if (CurItem->asTextFrame())
+		CurItem->asTextFrame()->updateUndo(CurItem->HasSel? PageItem::PARAMSEL : PageItem::PARAMFULL);
 }

 void PropertiesPalette::setTScale(double e)
@@ -3386,7 +3433,11 @@
 {
        if (!HaveDoc || !HaveItem || !m_ScMW || m_ScMW->scriptIsRunning())
                return;
+	if (CurItem->asTextFrame())
+		CurItem->itemTextSaxed = CurItem->getItemTextSaxed(doc->appMode == modeEdit? PageItem::SELECTION : PageItem::FRAME);
        doc->itemSelection_SetScaleH(qRound(ChScale->value() * 10));
+	if (CurItem->asTextFrame())
+		CurItem->asTextFrame()->updateUndo(CurItem->HasSel? PageItem::PARAMSEL : PageItem::PARAMFULL);
 }

 void PropertiesPalette::NewX()
@@ -3810,7 +3861,15 @@
 {
        if (!HaveDoc || !HaveItem || !m_ScMW || m_ScMW->scriptIsRunning())
                return;
+	if (CurItem->asTextFrame())
+	{
+//		CurItem->asTextFrame()->ExpandParSel();
+		CurItem->itemTextSaxed = CurItem->getItemTextSaxed(doc->appMode == modeEdit? PageItem::PARAGRAPH : PageItem::FRAME);
+//		CurItem->asTextFrame()->lastAction4Paragraph = true;
+	}
        doc->itemSelection_SetLineSpacing(LineSp->value());
+	if (CurItem->asTextFrame())
+		CurItem->asTextFrame()->updateUndo();
 }

 void PropertiesPalette::HandleGapSwitch()
@@ -3872,14 +3931,22 @@
 {
        if (!HaveDoc || !HaveItem || !m_ScMW || m_ScMW->scriptIsRunning())
                return;
+	if (CurItem->asTextFrame())
+		CurItem->itemTextSaxed = CurItem->getItemTextSaxed(doc->appMode == modeEdit? PageItem::SELECTION : PageItem::FRAME);
        doc->itemSelection_SetFontSize(qRound(Size->value()*10.0));
+	if (CurItem->asTextFrame())
+		CurItem->asTextFrame()->updateUndo(CurItem->HasSel? PageItem::PARAMSEL : PageItem::PARAMFULL);
 }

 void PropertiesPalette::NewTracking()
 {
        if (!HaveDoc || !HaveItem || !m_ScMW || m_ScMW->scriptIsRunning())
                return;
+	if (CurItem->asTextFrame())
+		CurItem->itemTextSaxed = CurItem->getItemTextSaxed(doc->appMode == modeEdit? PageItem::SELECTION : PageItem::FRAME);
        doc->itemSelection_SetTracking(qRound(Extra->value() * 10.0));
+	if (CurItem->asTextFrame())
+		CurItem->asTextFrame()->updateUndo(CurItem->HasSel? PageItem::PARAMSEL : PageItem::PARAMFULL);
 }

 void PropertiesPalette::NewLocalXY()
@@ -4197,25 +4264,72 @@

 void PropertiesPalette::NewAlignement(int a)
 {
+	int StartSel = 0, EndSel = 0, LenSel = 0;
        if (!HaveDoc || !HaveItem || !m_ScMW || m_ScMW->scriptIsRunning())
                return;
+	if (CurItem->asTextFrame())
+	{
+		// hack for apply left align for text with no align at all
+		//so during Undo/Redo some align will be applied
+		if (doc->appMode == modeEdit)
+		{
+			//selected parapgraph(s) only
+			CurItem->asTextFrame()->ExpandParSel();
+			StartSel = CurItem->itemText.startOfSelection();
+			EndSel = CurItem->itemText.endOfSelection();
+			for (uint i = CurItem->itemText.nrOfParagraph(StartSel); i <= CurItem->itemText.nrOfParagraph(EndSel); i++)
+			{
+				if (CurItem->itemText.paragraphStyle(CurItem->itemText.startOfParagraph(i)).alignment() == 0)
+				{
+					CurItem->itemText.select(CurItem->itemText.startOfParagraph(i), CurItem->itemText.endOfParagraph(i) - CurItem->itemText.startOfParagraph(i));
+					CurItem->HasSel = true;
+					doc->itemSelection_SetAlignment(0);
+				}
+			}
+		}
+		else
+		{
+			//for whole frame
+			for (uint i = 0; i <= CurItem->itemText.nrOfParagraph(CurItem->itemText.lastInFrame()); i++)
+			{
+				if (CurItem->itemText.paragraphStyle(CurItem->itemText.startOfParagraph(i)).alignment() == 0)
+				{
+					CurItem->CPos = CurItem->itemText.startOfParagraph(i);
+					doc->itemSelection_SetAlignment(0);
+				}
+
+			}
+		}
+		CurItem->itemTextSaxed = CurItem->getItemTextSaxed(doc->appMode == modeEdit? PageItem::PARAGRAPH : PageItem::FRAME);
+//		CurItem->asTextFrame()->lastAction4Paragraph = true;
+	}
        doc->itemSelection_SetAlignment(a);
+	if (CurItem->asTextFrame())
+		CurItem->asTextFrame()->updateUndo();
 }

 void PropertiesPalette::setTypeStyle(int s)
 {
        if (!m_ScMW || m_ScMW->scriptIsRunning())
                return;
+	if (CurItem->asTextFrame())
+		CurItem->itemTextSaxed = CurItem->getItemTextSaxed(doc->appMode == modeEdit? PageItem::SELECTION : PageItem::FRAME);
        emit NewEffects(s);
+	if (CurItem->asTextFrame())
+		CurItem->asTextFrame()->updateUndo(CurItem->HasSel? PageItem::PARAMSEL : PageItem::PARAMFULL);
 }

 void PropertiesPalette::newShadowOffs()
 {
        if ((HaveDoc) && (HaveItem))
        {
+		if (CurItem->asTextFrame())
+			CurItem->itemTextSaxed = CurItem->getItemTextSaxed(doc->appMode == modeEdit? PageItem::SELECTION : PageItem::FRAME);
                int x = qRound(SeStyle->ShadowVal->Xoffset->value() * 10.0);
                int y = qRound(SeStyle->ShadowVal->Yoffset->value() * 10.0);
                doc->itemSelection_SetShadowOffsets(x, y);
+		if (CurItem->asTextFrame())
+			CurItem->asTextFrame()->updateUndo(CurItem->HasSel? PageItem::PARAMSEL : PageItem::PARAMFULL);
        }
 }

@@ -4235,9 +4349,13 @@
 {
        if ((HaveDoc) && (HaveItem))
        {
+		if (CurItem->asTextFrame())
+			CurItem->itemTextSaxed = CurItem->getItemTextSaxed(doc->appMode == modeEdit? PageItem::SELECTION : PageItem::FRAME);
                int x = qRound(SeStyle->UnderlineVal->LPos->value() * 10.0);
                int y = qRound(SeStyle->UnderlineVal->LWidth->value() * 10.0);
                doc->itemSelection_SetUnderline(x, y);
+		if (CurItem->asTextFrame())
+			CurItem->asTextFrame()->updateUndo(CurItem->HasSel? PageItem::PARAMSEL : PageItem::PARAMFULL);
        }
 }

@@ -4257,9 +4375,13 @@
 {
        if ((HaveDoc) && (HaveItem))
        {
+		if (CurItem->asTextFrame())
+			CurItem->itemTextSaxed = CurItem->getItemTextSaxed(doc->appMode == modeEdit? PageItem::SELECTION : PageItem::FRAME);
                int x = qRound(SeStyle->StrikeVal->LPos->value() * 10.0);
                int y = qRound(SeStyle->StrikeVal->LWidth->value() * 10.0);
                doc->itemSelection_SetStrikethru(x, y);
+		if (CurItem->asTextFrame())
+			CurItem->asTextFrame()->updateUndo(CurItem->HasSel? PageItem::PARAMSEL : PageItem::PARAMFULL);
        }
 }

@@ -4288,7 +4410,13 @@
 {
        int x = qRound(SeStyle->OutlineVal->LWidth->value() * 10.0);
        if ((HaveDoc) && (HaveItem))
+	{
+		if (CurItem->asTextFrame())
+			CurItem->itemTextSaxed = CurItem->getItemTextSaxed(doc->appMode == modeEdit? PageItem::SELECTION : PageItem::FRAME);
                doc->itemSelection_SetOutlineWidth(x);
+		if (CurItem->asTextFrame())
+			CurItem->asTextFrame()->updateUndo(CurItem->HasSel? PageItem::PARAMSEL : PageItem::PARAMFULL);
+	}
 }

 void PropertiesPalette::DoLower()
@@ -4614,7 +4742,11 @@
                return;
        if (HaveDoc)
        {
+		if (CurItem->asTextFrame())
+			CurItem->itemTextSaxed = CurItem->getItemTextSaxed(doc->appMode == modeEdit? PageItem::SELECTION : PageItem::FRAME);
                doc->itemSelection_EraseCharStyle();
+		if (CurItem->asTextFrame())
+			CurItem->asTextFrame()->updateUndo(doc->appMode == modeEdit? PageItem::PARAMSEL : PageItem::PARAMFULL);
        }
 }

@@ -4625,9 +4757,17 @@
                return;
        if (HaveDoc)
        {
+		if (CurItem->asTextFrame())
+		{
+//			CurItem->asTextFrame()->ExpandParSel();
+			CurItem->itemTextSaxed = CurItem->getItemTextSaxed(doc->appMode == modeEdit? PageItem::PARAGRAPH : PageItem::FRAME);
+//			CurItem->asTextFrame()->lastAction4Paragraph = true;
+		}
                doc->itemSelection_EraseParagraphStyle();
                CharStyle emptyCStyle;
                doc->itemSelection_SetCharStyle(emptyCStyle);
+		if (CurItem->asTextFrame())
+			CurItem->asTextFrame()->updateUndo(doc->appMode == modeEdit ? PageItem::PARAMSEL : PageItem::PARAMFULL);
        }
 }

@@ -4773,14 +4913,23 @@
 {
        if (!HaveDoc || !HaveItem || !m_ScMW || m_ScMW->scriptIsRunning())
                return;
+	if (CurItem->asTextFrame())
+		CurItem->itemTextSaxed = CurItem->getItemTextSaxed(doc->appMode == modeEdit? PageItem::SELECTION : PageItem::FRAME);
        doc->itemSelection_SetFillColor(TxFill->currentColor());
+	if (CurItem->asTextFrame())
+		CurItem->asTextFrame()->updateUndo(CurItem->HasSel? PageItem::PARAMSEL : PageItem::PARAMFULL);
 }

 void PropertiesPalette::newTxtStroke()
 {
        if (!HaveDoc || !HaveItem || !m_ScMW || m_ScMW->scriptIsRunning())
                return;
+	if (CurItem->asTextFrame())
+		CurItem->itemTextSaxed = CurItem->getItemTextSaxed(doc->appMode == modeEdit? PageItem::SELECTION : PageItem::FRAME);
        doc->itemSelection_SetStrokeColor(TxStroke->currentColor());
+	if (CurItem->asTextFrame())
+		CurItem->asTextFrame()->updateUndo(CurItem->HasSel? PageItem::PARAMSEL : PageItem::PARAMFULL);
+
 }

 void PropertiesPalette::setActShade()
@@ -4788,6 +4937,8 @@
        if (!HaveDoc || !HaveItem || !m_ScMW || m_ScMW->scriptIsRunning())
                return;
        int b;
+	if (CurItem->asTextFrame())
+		CurItem->itemTextSaxed = CurItem->getItemTextSaxed(doc->appMode == modeEdit? PageItem::SELECTION : PageItem::FRAME);
        if (PM1 == sender())
        {
                b = PM1->getValue();
@@ -4798,6 +4949,8 @@
                b = PM2->getValue();
                doc->itemSelection_SetFillShade(b);
        }
+	if (CurItem->asTextFrame())
+		CurItem->asTextFrame()->updateUndo(CurItem->HasSel? PageItem::PARAMSEL : PageItem::PARAMFULL);
 }

 void PropertiesPalette::setActFarben(QString p, QString b, double shp, double shb)
@@ -4945,6 +5098,10 @@
                return;
        CurItem->fillRule = EvenOdd->isChecked();
        CurItem->update();
+	qDebug() << "PropertiesPalette::handleFillRule() updateUNDO";
+	if (CurItem->asTextFrame())
+		CurItem->asTextFrame()->updateUndo();
+
        emit DocChanged();
 }

@@ -5028,6 +5185,11 @@
                TabManager *dia = new TabManager(this, doc->unitIndex(), style.tabValues(), i2->columnWidth());
                if (dia->exec())
                {
+			if (CurItem->asTextFrame())
+			{
+				CurItem->itemTextSaxed = CurItem->getItemTextSaxed(doc->appMode == modeEdit? PageItem::PARAGRAPH : PageItem::FRAME);
+//				CurItem->asTextFrame()->lastAction4Paragraph = true;
+			}
                        if (doc->appMode != modeEdit)
                        {
                                ParagraphStyle newStyle(CurItem->itemText.defaultStyle());
@@ -5041,6 +5203,9 @@
                                doc->itemSelection_ApplyParagraphStyle(newStyle);
                        }
                        CurItem->update();
+			if (CurItem->asTextFrame())
+				CurItem->asTextFrame()->updateUndo();
+
                        emit DocChanged();
                }
                delete dia;
Index: Scribus/scribus/undomanager.cpp
===================================================================
--- Scribus/scribus/undomanager.cpp	(wersja 16088)
+++ Scribus/scribus/undomanager.cpp	(kopia robocza)
@@ -525,6 +526,11 @@
        target->setUName(oldName);
 }

+UndoState* UndoManager::getLastUndoState()
+{
+	return stacks_[currentDoc_].undoActions_[0];
+}
+
 void UndoManager::undo(int steps)
 {
        if (!undoEnabled_)
@@ -958,6 +964,7 @@
        UndoManager::Copy               = tr("Copy");
        UndoManager::CopyPage           = tr("Copy page");
        UndoManager::ToOutlines         = tr("Convert to outlines");
+	UndoManager::EditText		= tr("Edit text");
 }

 void UndoManager::initIcons()
@@ -1158,6 +1165,7 @@
 QString UndoManager::Copy               = "";
 QString UndoManager::CopyPage           = "";
 QString UndoManager::ToOutlines         = "";
+QString UndoManager::EditText		= "";

 /*** Icons for UndoObjects *******************************************/
 QPixmap *UndoManager::IImageFrame      = 0;
Index: Scribus/scribus/loremipsum.cpp
===================================================================
--- Scribus/scribus/loremipsum.cpp	(wersja 16088)
+++ Scribus/scribus/loremipsum.cpp	(kopia robocza)
@@ -311,6 +311,7 @@
                        continue;
                if (currItem->itemText.length() != 0)
                {
+			currItem->itemTextSaxed = currItem->getItemTextSaxed(PageItem::FRAME);
                        m_Doc->itemSelection_ClearItem();
                        /* ClearItem() doesn't return true or false so
                        the following test has to be done */
@@ -342,7 +343,12 @@
 #endif

                // K.I.S.S.:
-		currItem->itemText.insertChars(0, lp->createLorem(paraCount, random));
+		QString Lorip = lp->createLorem(paraCount, random);
+		currItem->itemText.insertChars(0, Lorip);
+		if (currItem->itemTextSaxed.isEmpty())
+			currItem->asTextFrame()->updateUndo(PageItem::INS,Lorip);
+		else
+			currItem->asTextFrame()->updateUndo(PageItem::REPSAX, currItem->getTextSaxed(Lorip));
                delete lp;

                //if (ScMW->view->SelItem.at(i)->Doc->docHyphenator->AutoCheck)
Index: Scribus/scribus/undomanager.h
===================================================================
--- Scribus/scribus/undomanager.h	(wersja 16088)
+++ Scribus/scribus/undomanager.h	(kopia robocza)
@@ -434,8 +434,11 @@
        void setTexts();

 public:
-
        /**
+	 * @brief Returns last saved Undo state
+	 */
+	UndoState* getLastUndoState();
+	/**
        * @name Action strings
        * Strings describing undo actions
        */
@@ -585,6 +588,7 @@
        static QString Copy;
        static QString CopyPage;
        static QString ToOutlines;
+	static QString EditText;
        /*@}*/

        /**
Index: Scribus/scribus/charselect.cpp
===================================================================
--- Scribus/scribus/charselect.cpp	(wersja 16088)
+++ Scribus/scribus/charselect.cpp	(kopia robocza)
@@ -15,6 +15,7 @@
 #include "scpaths.h"
 #include "scribusdoc.h"
 #include "scribusview.h"
+#include "undomanager.h"
 #include "util.h"
 #include "util_icon.h"
 #include "charselectenhanced.h"
@@ -106,16 +107,20 @@
 void CharSelect::slot_insertSpecialChar()
 {
        emit insertSpecialChar();
-
        if (!m_Item)
                return;
-
        if (m_Item->HasSel)
+	{
+		m_Item->itemTextSaxed = m_Item->getItemTextSaxed(PageItem::SELECTION);
                m_Item->asTextFrame()->deleteSelectedTextFromFrame();
+		m_Item->asTextFrame()->lastUndoAction = PageItem::NOACTION;
+	}
        if (m_Item->asTextFrame())
                m_Item->asTextFrame()->invalidateLayout();
        //CB: Avox please make text->insertchar(char) so none of this happens in gui code, and item can tell doc its changed so the view and mainwindow slotdocch are not necessary
        QChar ch;
+	QString txtIns;
+	m_Item->oldCPos = m_Item->CPos;
        for (int a=0; a<chToIns.length(); ++a)
        {
                ch = chToIns.at(a);
@@ -125,7 +130,12 @@
                        ch = QChar(32);
                m_Item->itemText.insertChars(m_Item->CPos, ch, true);
                m_Item->CPos += 1;
+		txtIns.append(ch);
        }
+	if (m_Item->itemTextSaxed.isEmpty())
+		m_Item->asTextFrame()->updateUndo(PageItem::INS, txtIns);
+	else
+		m_Item->asTextFrame()->updateUndo(PageItem::REPSAX, m_Item->getTextSaxed(txtIns));
        m_doc->updateFrameItems();
        m_doc->view()->DrawNew();
        m_doc->changed();
@@ -137,7 +147,11 @@
        if (!m_Item)
                return;
        if (m_Item->HasSel)
+	{
+		m_Item->itemTextSaxed = m_Item->getItemTextSaxed(PageItem::SELECTION);
                m_Item->asTextFrame()->deleteSelectedTextFromFrame();
+		m_Item->asTextFrame()->lastUndoAction = PageItem::NOACTION;
+	}
        if (m_Item->asTextFrame())
                m_Item->asTextFrame()->invalidateLayout();
 // 	//CB: Avox please make text->insertchar(char) so none of this happens in gui code, and item can tell doc its changed so the view and mainwindow slotdocch are not necessary
@@ -145,7 +159,12 @@
                ch = QChar(13);
        if (ch == QChar(9))
                ch = QChar(32);
+	m_Item->oldCPos = m_Item->CPos;
        m_Item->itemText.insertChars(m_Item->CPos, ch, true);
+	if (m_Item->itemTextSaxed.isEmpty())
+		m_Item->asTextFrame()->updateUndo(PageItem::INS, QString(ch));
+	else
+		m_Item->asTextFrame()->updateUndo(PageItem::REPSAX, m_Item->getTextSaxed(QString(ch)));
        m_doc->updateFrameItems();
        m_Item->CPos += 1;
        m_doc->view()->DrawNew();
Index: Scribus/scribus/canvasmode_edit.cpp
===================================================================
--- Scribus/scribus/canvasmode_edit.cpp	(wersja 16160)
+++ Scribus/scribus/canvasmode_edit.cpp	(kopia robocza)
@@ -375,6 +377,7 @@
        PageItem *currItem = 0;
        if (GetItem(&currItem) && (m_doc->appMode == modeEdit) && currItem->asTextFrame())
        {
+		currItem->asTextFrame()->lastUndoAction = PageItem::NOACTION;
                //CB if annotation, open the annotation dialog
                if (currItem->isAnnotation())
                {
@@ -619,7 +622,10 @@
                                                qApp->changeOverrideCursor(QCursor(Qt::ArrowCursor));
                                        }
                                        if (currItem->asTextFrame())
+					{
                                                m_view->slotSetCurs(m->globalPos().x(), m->globalPos().y());
+						currItem->asTextFrame()->lastUndoAction = PageItem::NOACTION;
+					}
                                }
                                else
                                {
@@ -636,6 +642,7 @@
                //CB Where we set the cursor for a click in text frame
                if (currItem->asTextFrame())
                {
+			currItem->asTextFrame()->lastUndoAction = PageItem::NOACTION;
                        inText = m_view->slotSetCurs(m->globalPos().x(), m->globalPos().y());
                        //CB If we clicked outside a text frame to go out of edit mode and deselect the frame
                        if (!inText)
@@ -644,6 +651,8 @@
                                m_view->Deselect(true);
                                //m_view->slotDoCurs(true);
                                m_view->requestMode(modeNormal);
+				if (currItem->isTextFrame())
+					currItem->asTextFrame()->lastUndoAction = PageItem::NOACTION;
                                return;
                        }

@@ -668,6 +677,7 @@
                                                        oldP = currItem->itemText.endOfSelection();
                                                }
                                                currItem->asTextFrame()->itemText.extendSelection(oldP, currItem->CPos);
+						currItem->asTextFrame()->lastUndoAction = PageItem::NOACTION;
                                                oldCp = currItem->CPos;
                                        }
                                        else
@@ -683,6 +693,7 @@
                                                                currItem->CPos = currItem->itemText.startOfParagraph(currItem->itemText.nrOfParagraph(currItem->CPos));
                                                }
                                                currItem->asTextFrame()->ExpandSel(dir, oldP);
+						currItem->asTextFrame()->lastUndoAction = PageItem::NOACTION;
                                                oldCp = oldP;
                                        }
                                }
@@ -690,6 +701,7 @@
                                {
                                        oldCp = currItem->CPos;
                                        currItem->itemText.deselectAll();
+					currItem->asTextFrame()->lastUndoAction = PageItem::NOACTION;
                                        currItem->HasSel = false;
                                }
                                currItem->emitAllToGUI();
@@ -704,7 +716,9 @@
                                        if (!cc.isNull())
                                        {
                                                // K.I.S.S.:
+						currItem->oldCPos = 0;
                                                currItem->itemText.insertChars(0, cc, true);
+						currItem->asTextFrame()->updateUndo(PageItem::INS,cc);
                                                if (m_doc->docHyphenator->AutoCheck)
                                                        m_doc->docHyphenator->slotHyphenate(currItem);
                                                m_ScMW->BookMarkTxT(currItem);
@@ -722,6 +736,7 @@
                else if (!currItem->asImageFrame() ||
                                 m_canvas->frameHitTest(QPointF(mousePointDoc.x(),mousePointDoc.y()), currItem) < 0)
                {
+			m_doc->m_Selection->delaySignalsOn();
                        m_view->Deselect(true);
                        if (SeleItem(m))
                        {
Index: Scribus/scribus/pageitem.h
===================================================================
--- Scribus/scribus/pageitem.h	(wersja 16088)
+++ Scribus/scribus/pageitem.h	(kopia robocza)
@@ -167,7 +167,24 @@
                TextFlowUsesContourLine = 3,
                TextFlowUsesImageClipping = 4
        };
+	//enum for actions in updateUndo and restoreEditText
+	typedef enum {
+		NOACTION = -1, //it is for checking if sequence of actions was done - after deselect text frame new sequence will be
+		PARAMFULL = 0, //parameters for whole frame
+		PARAMSEL = 1,  //paramaters for selected text
+		DELSAX = 2,	//delete with styles
+		INSSAX = 3,	//insert with styles
+		REPSAX = 4,	//replace with styles
+		INS = 5		//inserting chars without styles (from keyboard)
+	} EditAct;

+	typedef enum {  // for recognise what was changing during text edition/changing
+		FRAME = 1,
+		PARAGRAPH = 2,
+		SELECTION = 3,
+		CHAR = 4
+	} EditActPlace;
+
        /* these do essentially the same as a dynamic cast but might be more readable */
        virtual PageItem_ImageFrame * asImageFrame() { return NULL; }
        virtual PageItem_Line * asLine() { return NULL; }
@@ -448,6 +465,11 @@
        int CPos;
   /** Text des Elements */
        StoryText itemText;
+  // for itemText undo purpose
+	int oldCPos;
+	QString itemTextSaxed;
+	QString getItemTextSaxed(EditActPlace undoItem);
+	QString getTextSaxed(QString str);
   /** Flag fuer PDF-Bookmark */
        bool isBookmark;
   /** Flag for redraw in EditMode */
@@ -1060,6 +1082,8 @@

        void restoreShapeContour(UndoState *state, bool isUndo);
        void restoreImageEffects(UndoState *state, bool isUndo);
+	void restoreEditText(SimpleState *state, bool isUndo);
+
        /*@}*/

        /**
Index: Scribus/scribus/pageitem_textframe.h
===================================================================
--- Scribus/scribus/pageitem_textframe.h	(wersja 16088)
+++ Scribus/scribus/pageitem_textframe.h	(kopia robocza)
@@ -66,6 +66,7 @@
        void deleteSelectedTextFromFrame();
        void setNewPos(int oldPos, int len, int dir);
        void ExpandSel(int dir, int oldPos);
+	void ExpandParSel(); //expand selection to whole paragrpah(s)
        void deselectAll();

        virtual void invalidateLayout();
@@ -104,7 +105,9 @@
 	void setShadow();
 	QString currentShadow;
 	QMap<QString,StoryText> shadows;
-	
+public:
+	void updateUndo(EditAct action = PARAMFULL, QString str = "");
+	EditAct lastUndoAction;
 private slots:
 	void slotInvalidateLayout();
 };
