Index: scribus/canvasmode_legacy.cpp
===================================================================
--- scribus/canvasmode_legacy.cpp	(wersja 17243)
+++ scribus/canvasmode_legacy.cpp	(kopia robocza)
@@ -1800,7 +1800,7 @@
 								// K.I.S.S.:
 								currItem->oldCPos = 0;
 								currItem->itemText.insertChars(0, cc, true);
-								currItem->asTextFrame()->updateUndo(PageItem::INS,cc);
+								currItem->asTextFrame()->updateUndo(PageItem::INS,ETEAinsertingText, cc);
 								if (m_doc->docHyphenator->AutoCheck)
 									m_doc->docHyphenator->slotHyphenate(currItem);
 								m_ScMW->BookMarkTxT(currItem);
Index: scribus/pageitem.cpp
===================================================================
--- scribus/pageitem.cpp	(wersja 17243)
+++ scribus/pageitem.cpp	(kopia robocza)
@@ -44,6 +44,7 @@
 #include "commonstrings.h"
 #include "cpalette.h"
 #include "guidemanager.h"
+#include "hruler.h"
 #include "page.h"
 #include "pageitem_latexframe.h"
 #include "pageitem_textframe.h"
@@ -1004,6 +1005,51 @@
 
 void PageItem::setGridOffset(double) { } // FIXME
 void PageItem::setGridDistance(double) { } // FIXME
+void PageItem::setColsGapDist(int newCols, double newGap, double newLeft, double newRight, double newTop, double newBottom)
+{
+	setUndoColsGapDist(newCols, newGap, newLeft, newRight, newTop, newBottom);
+	setColumns(newCols);
+	setColumnGap(newGap);
+	setTextToFrameDist(newLeft, newRight, newTop, newBottom);
+}
+void PageItem::setUndoColsGapDist(int newCols, double newGap, double newLeft, double newRight, double newTop, double newBottom)
+{
+	if (UndoManager::undoEnabled())
+	{
+		SimpleState * ss = NULL;
+		if (asTextFrame()->getLastUndoAction() == STORY && asTextFrame()->getLastETEA() == ETEAsetColsGapDist)
+			ss = (SimpleState*) undoManager->getLastUndoState();
+		if (ss && ss->undoObject() == this && ss->contains("COLSGAPDIST"))
+		{
+			ss->set("NEW_COLS", newCols);
+			ss->set("NEW_GAP", newGap);
+			ss->set("NEW_DLEFT", newLeft);
+			ss->set("NEW_DRIGHT", newRight);
+			ss->set("NEW_DTOP", newTop);
+			ss->set("NEW_DBOTTOM", newBottom);
+		}
+		else
+		{
+			ss = new SimpleState(Um::SetColsGapDist);
+			ss->set("COLSGAPDIST","ColsGapDist");
+			ss->set("OLD_COLS", Cols);
+			ss->set("NEW_COLS", newCols);
+			ss->set("OLD_GAP", ColGap);
+			ss->set("NEW_GAP", newGap);
+			ss->set("OLD_DLEFT", Extra);
+			ss->set("NEW_DLEFT", newLeft);
+			ss->set("OLD_DRIGHT", RExtra);
+			ss->set("NEW_DRIGHT", newRight);
+			ss->set("OLD_DTOP", TExtra);
+			ss->set("NEW_DTOP", newTop);
+			ss->set("OLD_DBOTTOM", BExtra);
+			ss->set("NEW_DBOTTOM", newBottom);
+			undoManager->action(this, ss);
+			asTextFrame()->setLastUndoAction(STORY);
+			asTextFrame()->setLastETEA(ETEAsetColsGapDist);
+		}
+	}
+}
 void PageItem::setColumns(int n) 
 {
 	Cols = qMax(1, n); //FIXME: undo
@@ -3300,6 +3346,10 @@
 			restoreUnlinkTextFrame(ss, isUndo);
 		else if (ss->contains("REVERSE_TEXT"))
 			restoreReverseText(ss, isUndo);
+		else if (ss->contains("COLSGAPDIST"))
+			restoreColsGapDist(ss, isUndo);
+		else if (ss->contains("FIRSTLINEOFFS"))
+			restoreFirstLineOffset(ss, isUndo);
 	}
 	if (!OnMasterPage.isEmpty())
 		m_Doc->setCurrentPage(oldCurrentPage);
@@ -3550,6 +3600,16 @@
 	//	m_Doc->chAbStyle(this, styleid);
 }
 
+void PageItem::restoreColsGapDist(SimpleState *state, bool isUndo)
+{
+	if (isUndo)
+		setColsGapDist(state->getInt("OLD_COLS"), state->getDouble("OLD_GAP"), state->getDouble("OLD_DLEFT"), state->getDouble("OLD_DRIGHT"), state->getDouble("OLD_DTOP"), state->getDouble("OLD_DBOTTOM"));
+	else
+		setColsGapDist(state->getInt("NEW_COLS"), state->getDouble("NEW_GAP"), state->getDouble("NEW_DLEFT"), state->getDouble("NEW_DRIGHT"), state->getDouble("NEW_DTOP"), state->getDouble("NEW_DBOTTOM"));
+	m_Doc->scMW()->selectItemsFromOutlines(this);
+	update();
+	asTextFrame()->clearLastUndoAction();
+}
 
 // FIXME: This must go into class ScribusDoc!
 // For now we'll just make it independent of 'this' -- AV
@@ -3715,6 +3775,16 @@
 	}
 }
 
+void PageItem::restoreFirstLineOffset(SimpleState *state, bool isUndo)
+{
+	if (isUndo)
+		setFirstLineOffset((FirstLineOffsetPolicy)state->getInt("OLD_FLOP"));
+	else
+		setFirstLineOffset((FirstLineOffsetPolicy)state->getInt("NEW_FLOP"));
+	update();
+	asTextFrame()->clearLastUndoAction();
+}
+
 void PageItem::restoreReverseText(UndoState *state, bool /*isUndo*/)
 {
 	if (!isTextFrame())
@@ -3894,10 +3964,13 @@
 {
 	if (!isTextFrame())
 		return;
-	itemText.deselectAll();
-	HasSel = false;
+	if (HasSel)
+	{
+		itemText.deselectAll();
+		HasSel = false;
+	}
 	EditAct action = (EditAct) state->getInt("STEXT");
-	if (action == PARAMFULL || action == PARAMSEL)
+	if (action == STORY || action == PARAGRAPH || action == SELECTION)
 	{
 		QString buffer;
 		if (isUndo)
@@ -3912,29 +3985,35 @@
 			dig.addRule("/SCRIBUSTEXT", desaxe::Result<StoryText>());
 			dig.parseMemory(buffer.toStdString().c_str(), buffer.length());
 			StoryText* story = dig.result<StoryText>();
-			if (action == PARAMFULL)
+			if (action == STORY)
 			{
 				itemText.selectAll();
 				itemText.clear();
 				itemText.append(*story);
 			}
-			else if (action == PARAMSEL)
+			else if (action == PARAGRAPH || action == SELECTION)
 			{
-				itemText.deselectAll();
 				int SelStart = state->getInt("STEXT_SELSTART");
-				itemText.select(SelStart,state->getInt("STEXT_SELLEN"));
+				int SelLen = state->getInt("STEXT_SELLEN");
+				itemText.select(SelStart,SelLen);
+				if (action == PARAGRAPH)
+					asTextFrame()->expandParaSelection(true);
 				asTextFrame()->deleteSelectedTextFromFrame();
+				itemText.insert(SelStart, *story);
 				int ItemLength = itemText.length();
-				itemText.insert(SelStart, *story);
 				// If we have inserted at end of text we have to restore trailing style
 				if (ItemLength == SelStart && story->length() > 0 && story->text(-1) != SpecialChars::PARSEP)
+				    itemText.setStyle(-1, story->paragraphStyle(story->length()));
+				itemText.deselectAll();
+				if (action == SELECTION)
 				{
-					itemText.setStyle(-1, story->paragraphStyle(story->length()));
+					itemText.select(SelStart, story->length());
+					HasSel = true;
+					itemText.setCursorPosition(itemText.endOfSelection() -1);
 				}
-				itemText.select(SelStart, story->length());
-				HasSel = true;
+				else // action == PARAPGRAPH
+					itemText.setCursorPosition(state->getInt("STEXT_CPOS"));
 			}
-			itemText.setCursorPosition( itemText.endOfSelection() );
 			delete story;
 		}
 		else { qDebug() << "UNDO buffer EMPTY";}
@@ -3973,6 +4052,7 @@
 		itemText.select(pos, story->length());
 		HasSel = true;
 		delete story;
+		itemText.setCursorPosition(itemText.endOfSelection());
 	}
 	else if (action == INSSAX || action == DELSAX)
 	{
@@ -3995,7 +4075,10 @@
 		else
 		{
 			//undo for DELSAX, redo for INSSAX
+			if (state->getBool("STEXT_DELBACK"))
+				pos -=story->length();
 			itemText.insert(pos, *story);
+			itemText.setCursorPosition(state->getInt("STEXT_CPOS"));
 		}
 		delete story;
 	}
@@ -4014,18 +4097,18 @@
 		}
 	}
 	// after Undo or Redo new actions should create new undoStates
-	asTextFrame()->lastUndoAction = NOACTION;
-
+	asTextFrame()->clearLastUndoAction();
 	m_Doc->scMW()->setTBvals(this);
 	update();
 }
 
-QString PageItem::getItemTextSaxed(EditActPlace undoItem)
+QString PageItem::getItemTextSaxed(EditAct action)
 {
 	if (!isTextFrame()) return "";
+	if (itemText.length() <= 0) return "";
 	StoryText iT(m_Doc);
 	iT.setDefaultStyle(itemText.defaultStyle());
-	if (undoItem == FRAME)
+	if (action == STORY)
 		iT.insert(0, itemText);
 	else
 	{
@@ -4035,13 +4118,23 @@
 			StartOldSel = itemText.startOfSelection();
 			LenOldSel = itemText.lengthOfSelection();
 		}
-		if (undoItem == PARAGRAPH)
+		if (action == PARAGRAPH)
 			asTextFrame()->expandParaSelection(true);
-		else if (undoItem == CHAR || !HasSel)
+		else if (action == SELECTION && !HasSel)
 		{
-			if (itemText.cursorPosition() >= itemText.length())
-				return  "";
-			itemText.select(itemText.cursorPosition(), 1);
+			//case when there was not any selection, action was not paragraph related
+			// so changes will be applied for one char on right of cursor position
+			//if cursor is not at the end of paragraph or text
+			int CPos = itemText.cursorPosition();
+			if (CPos >= itemText.length()
+			        || itemText.text(CPos) == SpecialChars::PARSEP
+			        || itemText.text(CPos) == SpecialChars::COLBREAK
+			        || itemText.text(CPos) == SpecialChars::FRAMEBREAK
+			        || itemText.text(CPos) == SpecialChars::LINEBREAK
+					|| itemText.text(CPos) == SpecialChars::OBJECT
+			        || itemText.text(CPos) == SpecialChars::SHYPHEN)
+				return "";
+			itemText.select(CPos, 1);
 		}
 		//is SELECTION
 		iT.insert(0, itemText, true);
@@ -4097,7 +4190,7 @@
 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->m_Selection->itemAt()->asTextFrame()->clearLastUndoAction();
 	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);
@@ -6028,12 +6121,30 @@
 void PageItem::setFirstLineOffset(FirstLineOffsetPolicy flop)
 {
 	if(firstLineOffsetP != flop)
+		firstLineOffsetP = flop;
+}
+void PageItem::setUndoFirstLineOffset(FirstLineOffsetPolicy flop)
+{
+	if(firstLineOffsetP != flop)
 	{
+		if (UndoManager::undoEnabled())
+		{
+			SimpleState * ss = NULL;
+			if (asTextFrame()->getLastUndoAction() == STORY && asTextFrame()->getLastETEA() == ETEAsetFirstLineOffset)
+				ss = (SimpleState*) undoManager->getLastUndoState();
+			if (ss && ss->undoObject() == this && ss->contains("FIRSTLINEOFFS"))
+				ss->set("NEW_FLOP", flop);
+			else
+			{
+				ss = new SimpleState(Um::SetFirstLineOffset);
+				ss->set("FIRSTLINEOFFS", "FirstLineOffset");
+				ss->set("OLD_FLOP", (int) firstLineOffsetP);
+				ss->set("NEW_FLOP", flop);
+				undoManager->action(this, ss);
+				asTextFrame()->setLastUndoAction(STORY);
+				asTextFrame()->setLastETEA(ETEAsetFirstLineOffset);
+			}
+		}
 		firstLineOffsetP = flop;
 	}
 }
-
-
-
-
-
Index: scribus/pageitem_textframe.cpp
===================================================================
--- scribus/pageitem_textframe.cpp	(wersja 17243)
+++ scribus/pageitem_textframe.cpp	(kopia robocza)
@@ -30,7 +30,7 @@
 #include <QRegion>
 #include <cassert>
 
-
+#include "actionmanager.h"
 #include "canvas.h"
 #include "commonstrings.h"
 #include "guidemanager.h"
@@ -2821,11 +2821,11 @@
 	PageItem *nextItem = this;
 	while (nextItem->prevInChain() != 0)
 		nextItem = nextItem->prevInChain();
-	nextItem->itemTextSaxed = nextItem->getItemTextSaxed(PageItem::FRAME); //for undo
+	nextItem->itemTextSaxed = nextItem->getItemTextSaxed(PageItem::STORY); //for undo
 	ParagraphStyle defaultStyle = nextItem->itemText.defaultStyle();
 	nextItem->itemText.clear();
 	nextItem->itemText.setDefaultStyle(defaultStyle);
-	nextItem->asTextFrame()->updateUndo(); //for undo
+	nextItem->asTextFrame()->updateUndo(PageItem::STORY, ETEAclearContents); //for undo
 	while (nextItem != 0)
 	{
 		nextItem->invalid = true;
@@ -2909,7 +2909,7 @@
 	case Qt::Key_Down:
 		if ( (buttonModifiers & Qt::ShiftModifier) == 0 )
 			deselectAll();
-		lastUndoAction = PageItem::NOACTION;
+		clearLastUndoAction();
 	}
 
 	if (unicodeTextEditMode)
@@ -2938,21 +2938,18 @@
 				{
 					itemTextSaxed = getItemTextSaxed(PageItem::SELECTION);
 					deleteSelectedTextFromFrame();
-					lastUndoAction = PageItem::NOACTION;
+					clearLastUndoAction();
 				}
 				if (conv < 31)
 					conv = 32;
 				if (conv == 32)
-				{
-					qDebug() << "SPACE conv?";
-					lastUndoAction = PageItem::NOACTION;
-				}
+					clearLastUndoAction();
 				oldCPos = itemText.cursorPosition();
 				itemText.insertChars(QString(QChar(conv)), true);
 				if (itemTextSaxed.isEmpty())
-					updateUndo(INS, QString(QChar(conv)));
+					updateUndo(INS, ETEAinsertingText, QString(QChar(conv)));
 				else
-					updateUndo(REPSAX, getTextSaxed(QString(QChar(conv))));
+					updateUndo(REPSAX, ETEAreplacingText, getTextSaxed(QString(QChar(conv))));
 //				Tinput = true;
 				m_Doc->scMW()->setTBvals(this);
 				update();
@@ -3245,7 +3242,7 @@
 				oldCPos = itemText.startOfSelection();
 				itemTextSaxed = getItemTextSaxed(PageItem::SELECTION);
 				deleteSelectedTextFromFrame();
-				updateUndo(DELSAX);
+				updateUndo(DELSAX, ETEAdeletingText);
 				m_Doc->scMW()->setTBvals(this);
 				update();
 //				view->RefreshItem(this);
@@ -3267,7 +3264,7 @@
 		oldCPos = itemText.startOfSelection();
 		itemTextSaxed = getItemTextSaxed(PageItem::SELECTION);
 		deleteSelectedTextFromFrame();
-		updateUndo(DELSAX);
+		updateUndo(DELSAX, ETEAdeletingText);
 		update();
 //		Tinput = false;
 		if ((cr == QChar(13)) && (itemText.length() != 0))
@@ -3283,10 +3280,10 @@
 		{
 			if (itemText.lengthOfSelection() > 0)
 			{
-				oldCPos = itemText.startOfSelection();
+				oldCPos = itemText.startOfSelection() + itemText.lengthOfSelection();
 				itemTextSaxed = getItemTextSaxed(PageItem::SELECTION);
 				deleteSelectedTextFromFrame();
-				updateUndo(DELSAX);
+				updateUndo(DELSAX, ETEAdeletingBackText);
 				m_Doc->scMW()->setTBvals(this);
 				update();
 			}
@@ -3297,14 +3294,16 @@
 		cr = itemText.text(qMax(itemText.cursorPosition() - 1,0),1);
 		if (itemText.lengthOfSelection() == 0)
 		{
+			oldCPos = itemText.cursorPosition();
 			itemText.setCursorPosition(-1, true);
 			itemText.select(itemText.cursorPosition(), 1, true);
 			HasSel = true;
 		}
-		oldCPos = itemText.startOfSelection();
+		else
+			oldCPos = itemText.startOfSelection() + itemText.lengthOfSelection();
 		itemTextSaxed = getItemTextSaxed(PageItem::SELECTION);
 		deleteSelectedTextFromFrame();
-		updateUndo(DELSAX);
+		updateUndo(DELSAX, ETEAdeletingBackText);
 //		Tinput = false;
 		if ((cr == QChar(13)) && (itemText.length() != 0))
 		{
@@ -3319,7 +3318,7 @@
 			itemText.setCursorPosition(firstInFrame());
 			if (BackBox != 0)
 			{
-				lastUndoAction = PageItem::NOACTION;
+				clearLastUndoAction();
 				view->Deselect(true);
 				if (BackBox->invalid)
 					BackBox->updateLayout();
@@ -3327,8 +3326,8 @@
 				m_Doc->scMW()->selectItemsFromOutlines(BackBox);
 			}
 		}
+		update();
 		m_Doc->scMW()->setTBvals(this);
-		update();
 //		view->RefreshItem(this);
 		break;
 	default:
@@ -3351,7 +3350,7 @@
 				oldCPos = itemText.startOfSelection();
 				itemTextSaxed = getItemTextSaxed(PageItem::SELECTION);
 				deleteSelectedTextFromFrame();
-				lastUndoAction = PageItem::NOACTION;
+				clearLastUndoAction();
 				doUpdate = true;
 			}
 			/*
@@ -3369,11 +3368,11 @@
 		{
 			oldCPos = itemText.cursorPosition();
 			itemText.insertChars(QString(SpecialChars::TAB), true);
-			lastUndoAction = PageItem::NOACTION;
+			clearLastUndoAction();
 			if (itemTextSaxed.isEmpty())
-				updateUndo(INS, QString(SpecialChars::TAB));
+				updateUndo(INS, ETEAmanageTabs, QString(SpecialChars::TAB));
 			else
-				updateUndo(REPSAX, getTextSaxed(QString(SpecialChars::TAB)));
+				updateUndo(REPSAX, ETEAmanageTabs, getTextSaxed(QString(SpecialChars::TAB)));
 //			Tinput = true;
 //			view->RefreshItem(this);
 			doUpdate = true;
@@ -3381,14 +3380,14 @@
 		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;
+				clearLastUndoAction();
 			if (lastUndoAction != PageItem::INS)
 				oldCPos = itemText.cursorPosition();
 			itemText.insertChars(uc, true);
 			if (itemTextSaxed.isEmpty())
-				updateUndo(INS, uc);
+				updateUndo(INS, ETEAinsertingText, uc);
 			else
-				updateUndo(REPSAX, getTextSaxed(uc));
+				updateUndo(REPSAX, ETEAreplacingText, getTextSaxed(uc));
 			if ((m_Doc->docHyphenator->AutoCheck) && (itemText.cursorPosition() > 1))
 			{
 				Twort = "";
@@ -3566,46 +3565,38 @@
 // 	layoutWeakLock = true;
 // 	update();
 	m_Doc->regionsChanged()->update(getBoundingRect());
-	lastUndoAction = PageItem::NOACTION;
+	clearLastUndoAction();
 }
 
-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();
-		LenSel = itemText.endOfParagraph() - StartSel;
-	}
-	itemText.select(StartSel, LenSel);
-	HasSel = true;
-}
-
 void PageItem_TextFrame::expandParaSelection(bool includeEOL)
 {
 	int selStart, selLength;
-	if (HasSel)
+	if (itemText.lengthOfSelection() >0)
 	{
+		if (itemText.cursorPosition() == itemText.endOfSelection() && itemText.cursorPosition() < itemText.length())
+			//hack for situation, when CPos is before first char of next paragraph
+			//it add unselected paragraph if cursor is at its beginning
+			itemText.select(itemText.startOfSelection(), itemText.lengthOfSelection() +1);
+			
+		//remove PARSEP from end of selection - will be added if includeEOL is true
+		if (itemText.text(itemText.endOfSelection()-1) == SpecialChars::PARSEP)
+		{
+			selStart = itemText.startOfSelection();
+			selLength = itemText.lengthOfSelection() -1;
+			itemText.deselectAll();
+			itemText.select(selStart, selLength);
+		}
 		//extend selection to whole paragraphs
 		selStart  = itemText.startOfParagraph(itemText.nrOfParagraph(itemText.startOfSelection()));
-		selLength = itemText.endOfParagraph(itemText.nrOfParagraph(itemText.endOfSelection())) - selStart;
+		selLength = itemText.endOfParagraph(itemText.nrOfParagraph(itemText.endOfSelection()-1)) - selStart;
 	}
 	else
 	{
-		//extend selection to whole paragraph
+		//extend selection to whole paragraph where is cursor
 		selStart  = itemText.startOfParagraph();
 		selLength = itemText.endOfParagraph() - selStart;
 	}
-	if (includeEOL)
+	if (includeEOL && itemText.text(selStart + selLength -1) != SpecialChars::PARSEP)
 		selLength += 1;
 	selLength = qMin(selLength, itemText.length() - selStart);
 
@@ -3874,25 +3865,41 @@
 	invalidateLayout();
 }
 
-void PageItem_TextFrame::updateUndo(EditAct action, QString str)
+
+void PageItem_TextFrame::updateUndo(EditAct action, exactlyTextEditAct newAction, QString str)
 {
 	if (UndoManager::undoEnabled() && undoManager->undoEnabled())
 	{
-		int oldSelStart = -1, oldSelLen = -1;
+		int oldSelStart = itemText.cursorPosition(), oldSelLen = 0;
 		oldSelLen = itemText.lengthOfSelection();
 		if (oldSelLen > 0)
 			oldSelStart = itemText.startOfSelection();
-		if (action == PARAMFULL && m_Doc->appMode == modeEdit)
+		int CPos = itemText.cursorPosition();
+		if (m_Doc->appMode == modeEdit && action == STORY && oldSelLen == 0 && CPos < itemText.length())
 		{
-			//action is for paragraph where cursor is
-			expandParaSelection(true);
-			action = PARAMSEL;
+			if (itemText.itemText(CPos) == SpecialChars::PARSEP
+			        || itemText.text(CPos) == SpecialChars::COLBREAK
+			        || itemText.text(CPos) == SpecialChars::FRAMEBREAK
+			        || itemText.text(CPos) == SpecialChars::LINEBREAK
+					|| itemText.item(CPos)->hasObject()
+			        || itemText.text(CPos) == SpecialChars::SHYPHEN)
+			//case if after cursor is special char, no selection, no paragraph related change
+			// FIX ME - if changes in PP are not applied for text lets disable it or let select word if nothing is selected
+			{
+				return;
+			}
+			else
+			{
+				//action for one character on the right from cursor
+				action = SELECTION;
+				itemText.select(CPos, 1);
+				HasSel = true;
+			}
 		}
-		if (itemText.cursorPosition() >= itemText.length() && itemTextSaxed.isEmpty() && action == PARAMFULL && m_Doc->appMode == modeEdit)
+		if (itemText.cursorPosition() >= itemText.length() && itemTextSaxed.isEmpty() && action == STORY && m_Doc->appMode == modeEdit)
 		{ 
-			//case when cursor is after last character without selection and nothing was and will be done
 			//changes will be ignored
-			lastUndoAction = PageItem::NOACTION;
+			clearLastUndoAction();
 			restoreTextSelection(oldSelStart, oldSelLen);
 			return;
 		}
@@ -3903,19 +3910,19 @@
 			ss = (SimpleState*) undoManager->getLastUndoState();
 			if (ss && ss->undoObject() == this)
 			{
-				if (action == PARAMFULL || action == PARAMSEL)
+				if (action == STORY || action == PARAGRAPH || action == SELECTION)
 				{
-					newState = false;
-					if (itemTextSaxed.length() > 0)
+					if (lastExactTextEditAction == newAction)
 					{
-						/*QString tmpStr = ss->get("STEXT_NEW");
-						newState = (tmpStr.length() > 0 && tmpStr != itemTextSaxed);*/
-						newState = true;
+						newState = false;
+						if (itemTextSaxed.length() > 0)
+						{
+							QString tmpStr = ss->get("STEXT_NEW");
+							newState = (tmpStr.length() > 0 && tmpStr != itemTextSaxed);
+						}
+						if (newState == false)
+							itemTextSaxed = ss->get("STEXT_OLD");
 					}
-					if (newState == false)
-					{
-						itemTextSaxed = ss->get("STEXT_OLD");
-					}
 				}
 				else if (action == INSSAX || action == INS)
 				{
@@ -3928,13 +3935,49 @@
 		}
 		if (newState)
 		{
-			ss = new SimpleState(UndoManager::EditText);
+			QString descript;
+			switch (action)
+			{
+			case STORY:
+				descript = tr("Changing whole text");
+				break;
+			case PARAGRAPH:
+				descript = tr("Changing selected paragraph(s)");
+				break;
+			case SELECTION:
+				descript = tr("Changing selected text");
+				break;
+			case INSSAX:
+			case INS:
+				descript.append(tr("Inserting text"));
+				break;
+			case DELSAX:
+				descript = tr("Deleting");
+				descript =+ " '" + str.left(20) + "'";
+				break;
+			case REPSAX:
+				descript = tr("Replacing");
+				descript =+ " '" + str.left(20) + "'";
+				break;
+			case NOACTION:
+			default:
+				break;
+			}
+			if (newAction != ETEAotherEditAction)
+				descript += "\n" + doc()->scMW()->actionManager->textEditActionDescriptions.value(newAction,"");
+			ss = new SimpleState(UndoManager::EditText, descript);
 			ss->set("STEXT_CPOS", oldCPos);
 		}
 		if (action == INSSAX || action == INS)
 			ss->set("STEXT_STR",str);
 		else if (action == DELSAX)
+		{
 			ss->set("STEXT_STR",itemTextSaxed);
+			if (newAction == ETEAdeletingBackText)
+				ss->set("STEXT_DELBACK", 1);
+			else
+				ss->set("STEXT_DELBACK", 0);
+		}
 		else if (action == REPSAX)
 		{
 			ss->set("STEXT_NEW",str);
@@ -3942,24 +3985,18 @@
 		}
 		else
 		{
-			if (action == PARAMFULL && m_Doc->appMode == modeEdit)
+			if (action == PARAGRAPH || action == SELECTION)
 			{
-				//action is for paragraph where cursor is
-				expandParaSelection(true);
-				action = PARAMSEL;
-			}
-			if (action == PARAMSEL)
-			{
+				if (action == PARAGRAPH)
+					expandParaSelection(true);
 				ss->set("STEXT_CPOS", itemText.cursorPosition());
 				ss->set("STEXT_SELSTART", itemText.startOfSelection());
 				ss->set("STEXT_SELLEN", itemText.lengthOfSelection());
 			}
 			ss->set("STEXT_OLD", itemTextSaxed);
-			itemTextSaxed = getItemTextSaxed((action == PARAMSEL) ? SELECTION : FRAME);
-			ss->set("STEXT_NEW", itemTextSaxed);
+			ss->set("STEXT_NEW", getItemTextSaxed(action));
 			if (QString::compare(ss->get("STEXT_OLD"),ss->get("STEXT_NEW")) == 0)
 			{
-				//nothing change - quit without set new Undo step
 				itemTextSaxed.clear();
 				restoreTextSelection(oldSelStart, oldSelLen);
 				if (newState)
@@ -3969,6 +4006,7 @@
 		}
 		itemTextSaxed.clear();
 		lastUndoAction = action;
+		lastExactTextEditAction = newAction;
 		ss->set("STEXT",(int) action);
 		if (newState)
 			undoManager->action(this, ss);
Index: scribus/scribus.cpp
===================================================================
--- scribus/scribus.cpp	(wersja 17243)
+++ scribus/scribus.cpp	(kopia robocza)
@@ -1118,9 +1118,10 @@
 							currItem->oldCPos = currItem->itemText.cursorPosition();
 						currItem->itemText.insertChars(QString(QChar(unicodevalue)), true);
 						if (currItem->itemTextSaxed.isEmpty())
-							currItem->asTextFrame()->updateUndo(PageItem::INS, QString(QChar(unicodevalue)));
+							currItem->asTextFrame()->updateUndo(PageItem::INS, ETEAinsertingText, QString(QChar(unicodevalue)));
 						else
-							currItem->asTextFrame()->updateUndo(PageItem::REPSAX, currItem->getTextSaxed(QString(QChar(unicodevalue))));
+							currItem->asTextFrame()->updateUndo(PageItem::REPSAX, ETEAreplacingText, currItem->getTextSaxed(QString(QChar(unicodevalue))));
+						currItem->itemText.setCursorPosition(currItem->itemText.cursorPosition() + 1);
 //						currItem->Tinput = true;
 						currItem->update();
 					}
@@ -1137,7 +1138,7 @@
 #else
 							currItem->oldCPos = currItem->itemText.cursorPosition() ;
 							currItem->itemText.insertChars(QString(SpecialChars::SHYPHEN), true);
-							currItem->asTextFrame()->updateUndo(PageItem::INS, QString(SpecialChars::SHYPHEN));
+							currItem->asTextFrame()->updateUndo(PageItem::INS, ETEAinsertingSpecChar, QString(SpecialChars::SHYPHEN));
 #endif
 //							currItem->Tinput = true;
 							currItem->update();
@@ -4346,7 +4347,7 @@
 			ImportSetup impsetup=gt->run();
 			if (impsetup.runDialog)
 			{
-				currItem->itemTextSaxed = currItem->getItemTextSaxed(PageItem::FRAME);
+				currItem->itemTextSaxed = currItem->getItemTextSaxed(PageItem::STORY);
 				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);
@@ -4354,7 +4355,7 @@
 						return;
 				}
 				gt->launchImporter(impsetup.importer, impsetup.filename, impsetup.textOnly, impsetup.encoding, false);
-				currItem->asTextFrame()->updateUndo();
+				currItem->asTextFrame()->updateUndo(PageItem::STORY, ETEAgetContent);
 			}
 			delete gt;
 			if (doc->docHyphenator->AutoCheck)
@@ -4381,7 +4382,7 @@
 	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);
+	currItem->itemTextSaxed = currItem->getItemTextSaxed(PageItem::STORY);
 	ScGTPluginManager::instance()->run();
 	if (doc->docHyphenator->AutoCheck)
 		doc->docHyphenator->slotHyphenate(currItem);
@@ -4390,7 +4391,7 @@
 		if (doc->Items->at(a)->isBookmark)
 			bookmarkPalette->BView->ChangeText(doc->Items->at(a));
 	}
-	currItem->asTextFrame()->updateUndo();
+	currItem->asTextFrame()->updateUndo(PageItem::STORY, ETEAgetContent);
 	view->DrawNew();
 	slotDocCh();
 }
@@ -4447,9 +4448,9 @@
 		if (impsetup.runDialog)
 		{
 			PageItem *currItem = doc->m_Selection->itemAt(0);
-			currItem->itemTextSaxed = currItem->getItemTextSaxed(PageItem::FRAME);
+			currItem->itemTextSaxed = currItem->getItemTextSaxed(PageItem::STORY);
 			gt->launchImporter(impsetup.importer, impsetup.filename, impsetup.textOnly, impsetup.encoding, true);
-			currItem->asTextFrame()->updateUndo();
+			currItem->asTextFrame()->updateUndo(PageItem::STORY, ETEAfileAppend);
 		}
 		delete gt;
 		//CB Hyphenating now emits doc changed, plus we change lang as appropriate
@@ -5030,6 +5031,7 @@
 				return;
 			currItem->oldCPos = currItem->itemText.startOfSelection();
 			//for undo
+			QString oldstr = currItem->itemText.text(currItem->itemText.startOfSelection(), currItem->itemText.lengthOfSelection());
 			currItem->itemTextSaxed = currItem->getItemTextSaxed(PageItem::SELECTION);
 
 			StoryText itemText(doc);
@@ -5050,7 +5052,7 @@
 
 			dynamic_cast<PageItem_TextFrame*>(currItem)->deleteSelectedTextFromFrame();
 			//for undo
-			currItem->asTextFrame()->updateUndo(PageItem::DELSAX);
+			currItem->asTextFrame()->updateUndo(PageItem::DELSAX, ETEAdeletingText, oldstr);
 			currItem->update();
 		}
 		else
@@ -5186,7 +5188,7 @@
 		{
 			PageItem_TextFrame *currItem = dynamic_cast<PageItem_TextFrame*>(doc->m_Selection->itemAt(0));
 			assert(currItem != NULL);
-			currItem->lastUndoAction = PageItem::NOACTION;
+			currItem->clearLastUndoAction();
 			if (currItem->HasSel)
 			{
 				//for text undo, storing current selection
@@ -5214,7 +5216,7 @@
 				currItem->itemText.select(currItem->oldCPos, 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->updateUndo(currItem->itemTextSaxed.isEmpty() ? PageItem::INSSAX : PageItem::REPSAX, ETEAinsertingText, currItem->getItemTextSaxed(PageItem::SELECTION));
 				currItem->itemText.deselectAll();
 
 				delete story;
@@ -5303,7 +5305,7 @@
 				currItem->itemText.select(currItem->oldCPos, currItem->itemText.cursorPosition() - 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));
+				currItem->updateUndo(currItem->itemTextSaxed.isEmpty() ? PageItem::INSSAX : PageItem::REPSAX, ETEAinsertingText, currItem->getItemTextSaxed(PageItem::SELECTION));
 			}
 			else
 			{
@@ -5318,10 +5320,9 @@
 				currItem->HasSel = true;
 				//if itemTextSaxed is not empty there was selection
 				if (currItem->itemTextSaxed.isEmpty())
-					currItem->updateUndo(PageItem::INS, text);
+					currItem->updateUndo(PageItem::INS, ETEAinsertingText, text);
 				else
-					currItem->updateUndo(PageItem::REPSAX, currItem->getTextSaxed(text));
-
+					currItem->updateUndo(PageItem::REPSAX, ETEAreplacingText, currItem->getTextSaxed(text));
 			}
 			currItem->update();
 		}
@@ -7052,11 +7053,10 @@
 	//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;
+		currItem->itemTextSaxed = currItem->getItemTextSaxed(doc->appMode == modeEdit? PageItem::SELECTION : PageItem::STORY);
 	doc->itemSelection_SetFont(nf2);
 	if (currItem->asTextFrame())
-		currItem->asTextFrame()->updateUndo(currItem->HasSel? PageItem::PARAMSEL : PageItem::PARAMFULL);
+		currItem->asTextFrame()->updateUndo(doc->appMode == modeEdit? PageItem::SELECTION : PageItem::STORY, ETEAsetNewFont);
 
 //	doc->currentStyle.charStyle().setFont((*doc->AllFonts)[nf2]);
 	view->DrawNew();
@@ -7067,8 +7067,7 @@
 {
 	PageItem *currItem = doc->m_Selection->itemAt(0);
 	if (currItem->asTextFrame())
-		currItem->itemTextSaxed = currItem->getItemTextSaxed(doc->appMode == modeEdit? PageItem::SELECTION : PageItem::FRAME);
-
+		currItem->itemTextSaxed = currItem->getItemTextSaxed(doc->appMode == modeEdit? PageItem::SELECTION : PageItem::STORY);
 	int c = id;
 	if (c != -1)
 		doc->itemSelection_SetFontSize(c*10);
@@ -7084,8 +7083,7 @@
 		}
 	}
 	if (currItem->asTextFrame())
-		currItem->asTextFrame()->updateUndo(currItem->HasSel? PageItem::PARAMSEL : PageItem::PARAMFULL);
-
+		currItem->asTextFrame()->updateUndo(doc->appMode == modeEdit? PageItem::SELECTION : PageItem::STORY, ETEAsetItemFSize);
 	propertiesPalette->setSize(c*10);
 // 	slotDocCh();
 }
@@ -7098,6 +7096,8 @@
 	if (doc->m_Selection->count() != 0)
 	{
 		PageItem *currItem = doc->m_Selection->itemAt(0);
+		if (currItem->asTextFrame())
+			currItem->itemTextSaxed = currItem->getItemTextSaxed(doc->appMode == modeEdit? PageItem::SELECTION : PageItem::STORY);
 		if (c != -1)
 		{
 			if ((currItem->itemType() == PageItem::TextFrame) || (currItem->itemType() == PageItem::PathText))
@@ -7121,6 +7121,8 @@
 			}
 			delete dia;
 		}
+		if (currItem->asTextFrame())
+			currItem->asTextFrame()->updateUndo(doc->appMode == modeEdit? PageItem::SELECTION : PageItem::STORY, ETEAsetItemShade);
 	}
 // 	slotDocCh();
 }
@@ -7485,15 +7487,19 @@
 		else */
 		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);
-		}
+			currItem->itemTextSaxed = currItem->getItemTextSaxed(doc->appMode == modeEdit? PageItem::PARAGRAPH : PageItem::STORY);
 		doc->itemSelection_SetNamedParagraphStyle(name);
 		if (currItem->asTextFrame())
-			currItem->asTextFrame()->updateUndo();
+			currItem->asTextFrame()->updateUndo(doc->appMode == modeEdit? PageItem::PARAGRAPH : PageItem::STORY, ETEAsetNewParStyle);
 		setTBvals(currItem);
+		bool parSel = false;
+		if (doc->appMode == modeEdit && currItem->itemText.lengthOfSelection() == 0 && currItem->asTextFrame())
+		{
+			currItem->asTextFrame()->expandParaSelection();
+			parSel = true;
+		}
+		if (parSel)
+			currItem->itemText.deselectAll();
 	}
 }
 
@@ -7509,10 +7515,10 @@
 		else */
 		PageItem *currItem = doc->m_Selection->itemAt(0);
 		if (currItem->asTextFrame())
-			currItem->itemTextSaxed = currItem->getItemTextSaxed(doc->appMode == modeEdit? PageItem::SELECTION : PageItem::FRAME);
+			currItem->itemTextSaxed = currItem->getItemTextSaxed(doc->appMode == modeEdit? PageItem::SELECTION : PageItem::STORY);
 		doc->itemSelection_SetNamedCharStyle(name);
 		if (currItem->asTextFrame())
-			currItem->asTextFrame()->updateUndo(currItem->HasSel? PageItem::PARAMSEL : PageItem::PARAMFULL);
+			currItem->asTextFrame()->updateUndo(doc->appMode == modeEdit? PageItem::SELECTION : PageItem::STORY, ETEAsetNewCharStyle);
 		setTBvals(currItem);
 	}
 }
Index: scribus/propertiespalette.cpp
===================================================================
--- scribus/propertiespalette.cpp	(wersja 17243)
+++ scribus/propertiespalette.cpp	(kopia robocza)
@@ -2947,11 +2947,10 @@
 	if ((HaveDoc) && (HaveItem))
 	{
 		if (CurItem->asTextFrame())
-			CurItem->itemTextSaxed = CurItem->getItemTextSaxed(doc->appMode == modeEdit? PageItem::PARAGRAPH : PageItem::FRAME);
+			CurItem->itemTextSaxed = CurItem->getItemTextSaxed(doc->appMode == modeEdit? PageItem::PARAGRAPH : PageItem::STORY);
 		doc->itemSelection_SetLineSpacingMode(id);
-		updateStyle(doc->appMode == modeEdit? CurItem->currentStyle() : CurItem->itemText.defaultStyle());
 		if (CurItem->asTextFrame())
-			CurItem->asTextFrame()->updateUndo();
+			CurItem->asTextFrame()->updateUndo(doc->appMode == modeEdit? PageItem::PARAGRAPH : PageItem::STORY, ETEAsetLineSpacingMode);
 	}
 }
 
@@ -3294,7 +3293,7 @@
 	if (!HaveDoc || !HaveItem || !m_ScMW || m_ScMW->scriptIsRunning())
 		return;
 	if (CurItem->asTextFrame())
-		CurItem->itemTextSaxed = CurItem->getItemTextSaxed(PageItem::FRAME);
+		CurItem->itemTextSaxed = CurItem->getItemTextSaxed(doc->appMode == modeEdit? PageItem::PARAGRAPH : PageItem::STORY);
 	int omt(ParagraphStyle::OM_None);
 //	if (optMarginCheckLeftProtruding->isChecked()) omt+=ParagraphStyle::OM_LeftProtruding;
 	if (optMarginRadioBoth->isChecked())
@@ -3306,7 +3305,7 @@
 
 	doc->itemSelection_SetOpticalMargins(omt);
 	if (CurItem->asTextFrame())
-		CurItem->asTextFrame()->updateUndo();
+		CurItem->asTextFrame()->updateUndo(doc->appMode == modeEdit? PageItem::PARAGRAPH : PageItem::STORY, ETEAsetOpticalMargins);
 }
 
 void PropertiesPalette::resetOpticalMargins()
@@ -3335,12 +3334,12 @@
 	if (!HaveDoc || !HaveItem || !m_ScMW || m_ScMW->scriptIsRunning())
 		return;
 	if (CurItem->asTextFrame())
-		CurItem->itemTextSaxed = CurItem->getItemTextSaxed(doc->appMode == modeEdit? PageItem::SELECTION : PageItem::FRAME);
+		CurItem->itemTextSaxed = CurItem->getItemTextSaxed(doc->appMode == modeEdit? PageItem::SELECTION : PageItem::STORY);
 	ParagraphStyle newStyle;
 	newStyle.setMinWordTracking(minWordTrackingSpinBox->value() / 100.0);
 	doc->itemSelection_ApplyParagraphStyle(newStyle);
 	if (CurItem->asTextFrame())
-		CurItem->asTextFrame()->updateUndo(CurItem->HasSel? PageItem::PARAMSEL : PageItem::PARAMFULL);
+		CurItem->asTextFrame()->updateUndo(CurItem->HasSel? PageItem::SELECTION : PageItem::STORY, ETEAsetMinWordTracking);
 }
 
 
@@ -3349,13 +3348,13 @@
 	if (!HaveDoc || !HaveItem || !m_ScMW || m_ScMW->scriptIsRunning())
 		return;
 	if (CurItem->asTextFrame())
-		CurItem->itemTextSaxed = CurItem->getItemTextSaxed(doc->appMode == modeEdit? PageItem::SELECTION : PageItem::FRAME);
+		CurItem->itemTextSaxed = CurItem->getItemTextSaxed(doc->appMode == modeEdit? PageItem::SELECTION : PageItem::STORY);
 	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);
+		CurItem->asTextFrame()->updateUndo(CurItem->HasSel? PageItem::SELECTION : PageItem::STORY, ETEAsetNormWordTracking);
 }
 
 void PropertiesPalette::setMinGlyphExtension()
@@ -3363,12 +3362,12 @@
 	if (!HaveDoc || !HaveItem || !m_ScMW || m_ScMW->scriptIsRunning())
 		return;
 	if (CurItem->asTextFrame())
-		CurItem->itemTextSaxed = CurItem->getItemTextSaxed(doc->appMode == modeEdit? PageItem::SELECTION : PageItem::FRAME);
+		CurItem->itemTextSaxed = CurItem->getItemTextSaxed(doc->appMode == modeEdit? PageItem::SELECTION : PageItem::STORY);
 	ParagraphStyle newStyle;
 	newStyle.setMinGlyphExtension(minGlyphExtSpinBox->value() / 100.0);
 	doc->itemSelection_ApplyParagraphStyle(newStyle);
 	if (CurItem->asTextFrame())
-		CurItem->asTextFrame()->updateUndo(CurItem->HasSel? PageItem::PARAMSEL : PageItem::PARAMFULL);
+		CurItem->asTextFrame()->updateUndo(CurItem->HasSel? PageItem::SELECTION : PageItem::STORY, ETEAsetMinGlyphExtension);
 }
 
 void PropertiesPalette::setMaxGlyphExtension()
@@ -3376,12 +3375,12 @@
 	if (!HaveDoc || !HaveItem || !m_ScMW || m_ScMW->scriptIsRunning())
 		return;
 	if (CurItem->asTextFrame())
-		CurItem->itemTextSaxed = CurItem->getItemTextSaxed(doc->appMode == modeEdit? PageItem::SELECTION : PageItem::FRAME);
+		CurItem->itemTextSaxed = CurItem->getItemTextSaxed(doc->appMode == modeEdit? PageItem::SELECTION : PageItem::STORY);
 	ParagraphStyle newStyle;
 	newStyle.setMaxGlyphExtension(maxGlyphExtSpinBox->value() / 100.0);
 	doc->itemSelection_ApplyParagraphStyle(newStyle);
 	if (CurItem->asTextFrame())
-		CurItem->asTextFrame()->updateUndo(CurItem->HasSel? PageItem::PARAMSEL : PageItem::PARAMFULL);
+		CurItem->asTextFrame()->updateUndo(CurItem->HasSel? PageItem::SELECTION : PageItem::STORY, ETEAsetMaxGlyphExtension);
 }
 
 
@@ -3400,10 +3399,10 @@
 	if (!HaveDoc || !HaveItem || !m_ScMW || m_ScMW->scriptIsRunning())
 		return;
 	if (CurItem->asTextFrame())
-		CurItem->itemTextSaxed = CurItem->getItemTextSaxed(doc->appMode == modeEdit? PageItem::SELECTION : PageItem::FRAME);
+		CurItem->itemTextSaxed = CurItem->getItemTextSaxed(doc->appMode == modeEdit? PageItem::SELECTION : PageItem::STORY);
 	doc->itemSelection_SetScaleV(qRound(ChScaleV->value() * 10));
 	if (CurItem->asTextFrame())
-		CurItem->asTextFrame()->updateUndo(CurItem->HasSel? PageItem::PARAMSEL : PageItem::PARAMFULL);
+		CurItem->asTextFrame()->updateUndo(CurItem->HasSel? PageItem::SELECTION : PageItem::STORY, ETEAnewTScale);
 }
 
 void PropertiesPalette::NewTBase()
@@ -3411,10 +3410,10 @@
 	if (!HaveDoc || !HaveItem || !m_ScMW || m_ScMW->scriptIsRunning())
 		return;
 	if (CurItem->asTextFrame())
-		CurItem->itemTextSaxed = CurItem->getItemTextSaxed(doc->appMode == modeEdit? PageItem::SELECTION : PageItem::FRAME);
+		CurItem->itemTextSaxed = CurItem->getItemTextSaxed(doc->appMode == modeEdit? PageItem::SELECTION : PageItem::STORY);
 	doc->itemSelection_SetBaselineOffset(qRound(ChBase->value() * 10));
 	if (CurItem->asTextFrame())
-		CurItem->asTextFrame()->updateUndo(CurItem->HasSel? PageItem::PARAMSEL : PageItem::PARAMFULL);
+		CurItem->asTextFrame()->updateUndo(CurItem->HasSel? PageItem::SELECTION : PageItem::STORY, ETEAnewTBase);
 }
 
 void PropertiesPalette::setTScale(double e)
@@ -3442,10 +3441,10 @@
 	if (!HaveDoc || !HaveItem || !m_ScMW || m_ScMW->scriptIsRunning())
 		return;
 	if (CurItem->asTextFrame())
-		CurItem->itemTextSaxed = CurItem->getItemTextSaxed(doc->appMode == modeEdit? PageItem::SELECTION : PageItem::FRAME);
+		CurItem->itemTextSaxed = CurItem->getItemTextSaxed(doc->appMode == modeEdit? PageItem::SELECTION : PageItem::STORY);
 	doc->itemSelection_SetScaleH(qRound(ChScale->value() * 10));
 	if (CurItem->asTextFrame())
-		CurItem->asTextFrame()->updateUndo(CurItem->HasSel? PageItem::PARAMSEL : PageItem::PARAMFULL);
+		CurItem->asTextFrame()->updateUndo(CurItem->HasSel? PageItem::SELECTION : PageItem::STORY, ETEAnewTScale);
 }
 
 void PropertiesPalette::NewX()
@@ -3870,10 +3869,10 @@
 	if (!HaveDoc || !HaveItem || !m_ScMW || m_ScMW->scriptIsRunning())
 		return;
 	if (CurItem->asTextFrame())
-		CurItem->itemTextSaxed = CurItem->getItemTextSaxed(doc->appMode == modeEdit? PageItem::PARAGRAPH : PageItem::FRAME);
+		CurItem->itemTextSaxed = CurItem->getItemTextSaxed(doc->appMode == modeEdit? PageItem::PARAGRAPH : PageItem::STORY);
 	doc->itemSelection_SetLineSpacing(LineSp->value());
 	if (CurItem->asTextFrame())
-		CurItem->asTextFrame()->updateUndo();
+		CurItem->asTextFrame()->updateUndo(doc->appMode == modeEdit? PageItem::PARAGRAPH : PageItem::STORY, ETEAnewLineSpacing);
 }
 
 void PropertiesPalette::HandleGapSwitch()
@@ -3893,7 +3892,7 @@
 {
 	if (!HaveDoc || !HaveItem || !m_ScMW || m_ScMW->scriptIsRunning())
 		return;
-	CurItem->Cols = DCol->value();
+	CurItem->setColsGapDist(DCol->value(), CurItem->ColGap, CurItem->textToFrameDistLeft(), CurItem->textToFrameDistRight(), CurItem->textToFrameDistTop(), CurItem->textToFrameDistBottom());
 	setCols(CurItem->Cols, CurItem->ColGap);
 	CurItem->update();
 	emit DocChanged();
@@ -3914,8 +3913,9 @@
 {
 	if (!HaveDoc || !HaveItem || !m_ScMW || m_ScMW->scriptIsRunning())
 		return;
+	double newGap;
 	if (colgapLabel->currentIndex() == 0)
-		CurItem->ColGap = dGap->value() / m_unitRatio;
+		newGap = dGap->value() / m_unitRatio;
 	else
 	{
 		double lineCorr;
@@ -3924,9 +3924,9 @@
 		else
 			lineCorr = 0;
 		double newWidth = dGap->value() / m_unitRatio;
-		double newGap = qMax(((CurItem->width() - CurItem->textToFrameDistLeft() - CurItem->textToFrameDistRight() - lineCorr) - (newWidth * CurItem->Cols)) / (CurItem->Cols - 1), 0.0);
-		CurItem->ColGap = newGap;
+		newGap = qMax(((CurItem->width() - CurItem->textToFrameDistLeft() - CurItem->textToFrameDistRight() - lineCorr) - (newWidth * CurItem->Cols)) / (CurItem->Cols - 1), 0.0);
 	}
+	CurItem->setColsGapDist(CurItem->Cols, newGap, CurItem->textToFrameDistLeft(), CurItem->textToFrameDistRight(), CurItem->textToFrameDistTop(), CurItem->textToFrameDistBottom());
 	CurItem->update();
 	emit DocChanged();
 }
@@ -3936,10 +3936,10 @@
 	if (!HaveDoc || !HaveItem || !m_ScMW || m_ScMW->scriptIsRunning())
 		return;
 	if (CurItem->asTextFrame())
-		CurItem->itemTextSaxed = CurItem->getItemTextSaxed(doc->appMode == modeEdit? PageItem::SELECTION : PageItem::FRAME);
+		CurItem->itemTextSaxed = CurItem->getItemTextSaxed(doc->appMode == modeEdit? PageItem::SELECTION : PageItem::STORY);
 	doc->itemSelection_SetFontSize(qRound(Size->value()*10.0));
 	if (CurItem->asTextFrame())
-		CurItem->asTextFrame()->updateUndo(CurItem->HasSel? PageItem::PARAMSEL : PageItem::PARAMFULL);
+		CurItem->asTextFrame()->updateUndo(CurItem->HasSel? PageItem::SELECTION : PageItem::STORY, ETEAnewSize);
 }
 
 void PropertiesPalette::NewTracking()
@@ -3947,10 +3947,10 @@
 	if (!HaveDoc || !HaveItem || !m_ScMW || m_ScMW->scriptIsRunning())
 		return;
 	if (CurItem->asTextFrame())
-		CurItem->itemTextSaxed = CurItem->getItemTextSaxed(doc->appMode == modeEdit? PageItem::SELECTION : PageItem::FRAME);
+		CurItem->itemTextSaxed = CurItem->getItemTextSaxed(doc->appMode == modeEdit? PageItem::SELECTION : PageItem::STORY);
 	doc->itemSelection_SetTracking(qRound(Extra->value() * 10.0));
 	if (CurItem->asTextFrame())
-		CurItem->asTextFrame()->updateUndo(CurItem->HasSel? PageItem::PARAMSEL : PageItem::PARAMFULL);
+		CurItem->asTextFrame()->updateUndo(CurItem->HasSel? PageItem::SELECTION : PageItem::STORY, ETEAnewTracking);
 }
 
 void PropertiesPalette::NewLocalXY()
@@ -4271,10 +4271,10 @@
 	if (!HaveDoc || !HaveItem || !m_ScMW || m_ScMW->scriptIsRunning())
 		return;
 	if (CurItem->asTextFrame())
-		CurItem->itemTextSaxed = CurItem->getItemTextSaxed(doc->appMode == modeEdit? PageItem::PARAGRAPH : PageItem::FRAME);
+		CurItem->itemTextSaxed = CurItem->getItemTextSaxed(doc->appMode == modeEdit? PageItem::PARAGRAPH : PageItem::STORY);
 	doc->itemSelection_SetAlignment(a);
 	if (CurItem->asTextFrame())
-		CurItem->asTextFrame()->updateUndo();
+		CurItem->asTextFrame()->updateUndo(doc->appMode == modeEdit? PageItem::PARAGRAPH : PageItem::STORY, ETEAnewAlignement);
 }
 
 void PropertiesPalette::setTypeStyle(int s)
@@ -4282,10 +4282,10 @@
 	if (!m_ScMW || m_ScMW->scriptIsRunning())
 		return;
 	if (CurItem->asTextFrame())
-		CurItem->itemTextSaxed = CurItem->getItemTextSaxed(doc->appMode == modeEdit? PageItem::SELECTION : PageItem::FRAME);
+		CurItem->itemTextSaxed = CurItem->getItemTextSaxed(doc->appMode == modeEdit? PageItem::SELECTION : PageItem::STORY);
 	emit NewEffects(s);
 	if (CurItem->asTextFrame())
-		CurItem->asTextFrame()->updateUndo(CurItem->HasSel? PageItem::PARAMSEL : PageItem::PARAMFULL);
+		CurItem->asTextFrame()->updateUndo(CurItem->HasSel? PageItem::SELECTION : PageItem::STORY, ETEAsetTypeStyle);
 }
 
 void PropertiesPalette::newShadowOffs()
@@ -4293,12 +4293,12 @@
 	if ((HaveDoc) && (HaveItem))
 	{
 		if (CurItem->asTextFrame())
-			CurItem->itemTextSaxed = CurItem->getItemTextSaxed(doc->appMode == modeEdit? PageItem::SELECTION : PageItem::FRAME);
+			CurItem->itemTextSaxed = CurItem->getItemTextSaxed(doc->appMode == modeEdit? PageItem::SELECTION : PageItem::STORY);
 		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);
+			CurItem->asTextFrame()->updateUndo(CurItem->HasSel? PageItem::SELECTION : PageItem::STORY, ETEAnewShadowOffs);
 	}
 }
 
@@ -4319,12 +4319,12 @@
 	if ((HaveDoc) && (HaveItem))
 	{
 		if (CurItem->asTextFrame())
-			CurItem->itemTextSaxed = CurItem->getItemTextSaxed(doc->appMode == modeEdit? PageItem::SELECTION : PageItem::FRAME);
+			CurItem->itemTextSaxed = CurItem->getItemTextSaxed(doc->appMode == modeEdit? PageItem::SELECTION : PageItem::STORY);
 		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);
+			CurItem->asTextFrame()->updateUndo(CurItem->HasSel? PageItem::SELECTION : PageItem::STORY, ETEAnewUnderline);
 	}
 }
 
@@ -4345,12 +4345,12 @@
 	if ((HaveDoc) && (HaveItem))
 	{
 		if (CurItem->asTextFrame())
-			CurItem->itemTextSaxed = CurItem->getItemTextSaxed(doc->appMode == modeEdit? PageItem::SELECTION : PageItem::FRAME);
+			CurItem->itemTextSaxed = CurItem->getItemTextSaxed(doc->appMode == modeEdit? PageItem::SELECTION : PageItem::STORY);
 		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);
+			CurItem->asTextFrame()->updateUndo(CurItem->HasSel? PageItem::SELECTION : PageItem::STORY, ETEAnewStrike);
 	}
 }
 
@@ -4381,10 +4381,10 @@
 	if ((HaveDoc) && (HaveItem))
 	{
 		if (CurItem->asTextFrame())
-			CurItem->itemTextSaxed = CurItem->getItemTextSaxed(doc->appMode == modeEdit? PageItem::SELECTION : PageItem::FRAME);
+			CurItem->itemTextSaxed = CurItem->getItemTextSaxed(doc->appMode == modeEdit? PageItem::SELECTION : PageItem::STORY);
 		doc->itemSelection_SetOutlineWidth(x);
 		if (CurItem->asTextFrame())
-			CurItem->asTextFrame()->updateUndo(CurItem->HasSel? PageItem::PARAMSEL : PageItem::PARAMFULL);
+			CurItem->asTextFrame()->updateUndo(CurItem->HasSel? PageItem::SELECTION : PageItem::STORY, ETEAnewOutlineW);
 	}
 }
 
@@ -4647,7 +4647,7 @@
 		return;
 	if ((HaveDoc) && (HaveItem))
 	{
-		CurItem->setTextToFrameDist(DLeft->value() / m_unitRatio, DRight->value() / m_unitRatio, DTop->value() / m_unitRatio, DBottom->value() / m_unitRatio);
+		CurItem->setColsGapDist(CurItem->Cols, CurItem->ColGap, DLeft->value() / m_unitRatio, DRight->value() / m_unitRatio, DTop->value() / m_unitRatio, DBottom->value() / m_unitRatio);
 		setCols(CurItem->Cols, CurItem->ColGap);
 		CurItem->update();
 		emit DocChanged();
@@ -4708,10 +4708,10 @@
 	if (HaveDoc)
 	{
 		if (CurItem->asTextFrame())
-			CurItem->itemTextSaxed = CurItem->getItemTextSaxed(doc->appMode == modeEdit? PageItem::SELECTION : PageItem::FRAME);
+			CurItem->itemTextSaxed = CurItem->getItemTextSaxed(doc->appMode == modeEdit? PageItem::SELECTION : PageItem::STORY);
 		doc->itemSelection_EraseCharStyle();
 		if (CurItem->asTextFrame())
-			CurItem->asTextFrame()->updateUndo(doc->appMode == modeEdit? PageItem::PARAMSEL : PageItem::PARAMFULL);
+			CurItem->asTextFrame()->updateUndo(doc->appMode == modeEdit? PageItem::SELECTION : PageItem::STORY, ETEAclearCStyle);
 	}
 }
 
@@ -4723,16 +4723,20 @@
 	if (HaveDoc)
 	{
 		if (CurItem->asTextFrame())
-		{
-//			CurItem->asTextFrame()->ExpandParSel();
-			CurItem->itemTextSaxed = CurItem->getItemTextSaxed(doc->appMode == modeEdit? PageItem::PARAGRAPH : PageItem::FRAME);
-//			CurItem->asTextFrame()->lastAction4Paragraph = true;
-		}
+			CurItem->itemTextSaxed = CurItem->getItemTextSaxed(doc->appMode == modeEdit? PageItem::PARAGRAPH : PageItem::STORY);
 		doc->itemSelection_EraseParagraphStyle();
 		CharStyle emptyCStyle;
 		doc->itemSelection_SetCharStyle(emptyCStyle);
 		if (CurItem->asTextFrame())
-			CurItem->asTextFrame()->updateUndo(doc->appMode == modeEdit ? PageItem::PARAMSEL : PageItem::PARAMFULL);
+			CurItem->asTextFrame()->updateUndo(doc->appMode == modeEdit ? PageItem::SELECTION : PageItem::STORY, ETEAclearPStyle);
+		bool parSel = false;
+		if (doc->appMode == modeEdit && CurItem->itemText.lengthOfSelection() == 0 && CurItem->asTextFrame())
+		{
+			CurItem->asTextFrame()->expandParaSelection();
+			parSel = true;
+		}
+		if (parSel)
+			CurItem->itemText.deselectAll();
 	}
 }
 
@@ -4879,10 +4883,10 @@
 	if (!HaveDoc || !HaveItem || !m_ScMW || m_ScMW->scriptIsRunning())
 		return;
 	if (CurItem->asTextFrame())
-		CurItem->itemTextSaxed = CurItem->getItemTextSaxed(doc->appMode == modeEdit? PageItem::SELECTION : PageItem::FRAME);
+		CurItem->itemTextSaxed = CurItem->getItemTextSaxed(doc->appMode == modeEdit? PageItem::SELECTION : PageItem::STORY);
 	doc->itemSelection_SetFillColor(TxFill->currentColor());
 	if (CurItem->asTextFrame())
-		CurItem->asTextFrame()->updateUndo(CurItem->HasSel? PageItem::PARAMSEL : PageItem::PARAMFULL);
+		CurItem->asTextFrame()->updateUndo(CurItem->HasSel? PageItem::SELECTION : PageItem::STORY, ETEAnewTxtFill);
 }
 
 void PropertiesPalette::newTxtStroke()
@@ -4890,10 +4894,10 @@
 	if (!HaveDoc || !HaveItem || !m_ScMW || m_ScMW->scriptIsRunning())
 		return;
 	if (CurItem->asTextFrame())
-		CurItem->itemTextSaxed = CurItem->getItemTextSaxed(doc->appMode == modeEdit? PageItem::SELECTION : PageItem::FRAME);
+		CurItem->itemTextSaxed = CurItem->getItemTextSaxed(doc->appMode == modeEdit? PageItem::SELECTION : PageItem::STORY);
 	doc->itemSelection_SetStrokeColor(TxStroke->currentColor());
 	if (CurItem->asTextFrame())
-		CurItem->asTextFrame()->updateUndo(CurItem->HasSel? PageItem::PARAMSEL : PageItem::PARAMFULL);
+		CurItem->asTextFrame()->updateUndo(CurItem->HasSel? PageItem::SELECTION : PageItem::STORY, ETEAnewTxtStroke);
 
 }
 
@@ -4903,7 +4907,7 @@
 		return;
 	int b;
 	if (CurItem->asTextFrame())
-		CurItem->itemTextSaxed = CurItem->getItemTextSaxed(doc->appMode == modeEdit? PageItem::SELECTION : PageItem::FRAME);
+		CurItem->itemTextSaxed = CurItem->getItemTextSaxed(doc->appMode == modeEdit? PageItem::SELECTION : PageItem::STORY);
 	if (PM1 == sender())
 	{
 		b = PM1->getValue();
@@ -4915,7 +4919,7 @@
 		doc->itemSelection_SetFillShade(b);
 	}
 	if (CurItem->asTextFrame())
-		CurItem->asTextFrame()->updateUndo(CurItem->HasSel? PageItem::PARAMSEL : PageItem::PARAMFULL);
+		CurItem->asTextFrame()->updateUndo(CurItem->HasSel? PageItem::SELECTION : PageItem::STORY, ETEAsetActShade);
 }
 
 void PropertiesPalette::setActFarben(QString p, QString b, double shp, double shb)
@@ -5065,7 +5069,7 @@
 	CurItem->update();
 	qDebug() << "PropertiesPalette::handleFillRule() updateUNDO";
 	if (CurItem->asTextFrame())
-		CurItem->asTextFrame()->updateUndo();
+		CurItem->asTextFrame()->updateUndo(PageItem::STORY);
 
 	emit DocChanged();
 }
@@ -5150,10 +5154,7 @@
 		if (dia->exec())
 		{
 			if (CurItem->asTextFrame())
-			{
-				CurItem->itemTextSaxed = CurItem->getItemTextSaxed(doc->appMode == modeEdit? PageItem::PARAGRAPH : PageItem::FRAME);
-//				CurItem->asTextFrame()->lastAction4Paragraph = true;
-			}
+				CurItem->itemTextSaxed = CurItem->getItemTextSaxed(doc->appMode == modeEdit? PageItem::PARAGRAPH : PageItem::STORY);
 			if (doc->appMode != modeEdit)
 			{
 				ParagraphStyle newStyle(CurItem->itemText.defaultStyle());
@@ -5168,7 +5169,7 @@
 			}
 			CurItem->update();
 			if (CurItem->asTextFrame())
-				CurItem->asTextFrame()->updateUndo();
+				CurItem->asTextFrame()->updateUndo(doc->appMode == modeEdit? PageItem::PARAGRAPH : PageItem::STORY, ETEAmanageTabs);
 
 			emit DocChanged();
 		}
@@ -5890,11 +5891,11 @@
 		return;
 // 	qDebug("%s", QString("rF %1").arg(radioFlop).toAscii());
 	if( radioFlop == 0)
-		CurItem->setFirstLineOffset(FLOPRealGlyphHeight);
+		CurItem->setUndoFirstLineOffset(FLOPRealGlyphHeight);
 	else if( radioFlop == 1)
-		CurItem->setFirstLineOffset(FLOPFontAscent);
+		CurItem->setUndoFirstLineOffset(FLOPFontAscent);
 	else if( radioFlop == 2)
-		CurItem->setFirstLineOffset(FLOPLineSpacing);
+		CurItem->setUndoFirstLineOffset(FLOPLineSpacing);
 	CurItem->update();
 	emit DocChanged();
 }
Index: scribus/undomanager.cpp
===================================================================
--- scribus/undomanager.cpp	(wersja 17243)
+++ scribus/undomanager.cpp	(kopia robocza)
@@ -882,6 +882,7 @@
 	UndoManager::StartAndEndArrow   = tr("Set start and end arrows");
 	UndoManager::CreateTable        = tr("Create table");
 	UndoManager::RowsCols           = tr("Rows: %1, Cols: %2");
+	UndoManager::SetColsGapDist     = tr("Set columns, gap and text distances");
 	UndoManager::SetFont            = tr("Set font");
 	UndoManager::SetFontSize        = tr("Set font size");
 	UndoManager::SetFontWidth       = tr("Set font width");
@@ -896,6 +897,7 @@
 	UndoManager::SetLanguage        = tr("Set language");
 	UndoManager::AlignText          = tr("Align text");
 	UndoManager::SetFontEffect      = tr("Set font effect");
+	UndoManager::SetFirstLineOffset = tr("Set first line offset");
 	UndoManager::ImageFrame         = tr("Image frame");
 	UndoManager::TextFrame          = tr("Text frame");
 	UndoManager::LatexFrame         = tr("Render frame");
@@ -1095,6 +1097,7 @@
 QString UndoManager::StartAndEndArrow   = "";
 QString UndoManager::CreateTable        = "";
 QString UndoManager::RowsCols           = "";
+QString UndoManager::SetColsGapDist     = "";
 QString UndoManager::SetFont            = "";
 QString UndoManager::SetFontSize        = "";
 QString UndoManager::SetFontWidth       = "";
@@ -1109,6 +1112,7 @@
 QString UndoManager::SetLanguage        = "";
 QString UndoManager::AlignText          = "";
 QString UndoManager::SetFontEffect      = "";
+QString UndoManager::SetFirstLineOffset = "";
 QString UndoManager::ImageFrame         = "";
 QString UndoManager::TextFrame          = "";
 QString UndoManager::LatexFrame         = "";
Index: scribus/actionmanager.h
===================================================================
--- scribus/actionmanager.h	(wersja 17243)
+++ scribus/actionmanager.h	(kopia robocza)
@@ -37,6 +37,7 @@
 
 #include "scribusapi.h"
 #include "scraction.h"
+#include "scribusstructs.h"
 
 class ScribusDoc;
 class ScribusMainWindow;
@@ -69,6 +70,7 @@
 		static QString defaultMenuNameEntryTranslated(const QString& index);
 		static QVector< QPair<QString, QStringList> >* defaultMenus() {return &defMenus;};
 		static QVector< QPair<QString, QStringList> >* defaultNonMenuActions() {return &defNonMenuActions;};
+		QMap<exactlyTextEditAct,QString> textEditActionDescriptions;
 		void createActions();
 		void disconnectModeActions();
 		void connectModeActions();
@@ -104,6 +106,7 @@
 		static void initUnicodeActions(QMap<QString, QPointer<ScrAction> > *actionMap, QWidget *actionParent, QStringList *actionNamesList);
 		void initSpecialActions();
 		static void languageChangeUnicodeActions(QMap<QString, QPointer<ScrAction> > *actionMap);
+		void initTextEditActionsDescriptions();
 		void languageChangeActions();
 		static QKeySequence defaultKey(const QString &actionName);
 	
Index: scribus/loremipsum.cpp
===================================================================
--- scribus/loremipsum.cpp	(wersja 17243)
+++ scribus/loremipsum.cpp	(kopia robocza)
@@ -311,7 +311,7 @@
 			continue;
 		if (currItem->itemText.length() != 0)
 		{
-			currItem->itemTextSaxed = currItem->getItemTextSaxed(PageItem::FRAME);
+			currItem->itemTextSaxed = currItem->getItemTextSaxed(PageItem::STORY);
 			m_Doc->itemSelection_ClearItem();
 			/* ClearItem() doesn't return true or false so
 			the following test has to be done */
@@ -346,9 +346,9 @@
 		QString Lorip = lp->createLorem(paraCount, random);
 		currItem->itemText.insertChars(0, Lorip);
 		if (currItem->itemTextSaxed.isEmpty())
-			currItem->asTextFrame()->updateUndo(PageItem::INS,Lorip);
+			currItem->asTextFrame()->updateUndo(PageItem::INS, ETEAinsertLoremIpsum, Lorip);
 		else
-			currItem->asTextFrame()->updateUndo(PageItem::REPSAX, currItem->getTextSaxed(Lorip));
+			currItem->asTextFrame()->updateUndo(PageItem::REPSAX, ETEAinsertLoremIpsum, currItem->getTextSaxed(Lorip));
 		delete lp;
 
 		//if (ScMW->view->SelItem.at(i)->Doc->docHyphenator->AutoCheck)
Index: scribus/undomanager.h
===================================================================
--- scribus/undomanager.h	(wersja 17243)
+++ scribus/undomanager.h	(kopia robocza)
@@ -508,6 +508,7 @@
 	static QString StartAndEndArrow;
 	static QString CreateTable;
 	static QString RowsCols;
+	static QString SetColsGapDist;
 	static QString SetFont;
 	static QString SetFontSize;
 	static QString SetFontWidth;
@@ -522,6 +523,7 @@
 	static QString SetLanguage;
 	static QString AlignText;
 	static QString SetFontEffect;
+	static QString SetFirstLineOffset;
 	static QString ImageFrame;
 	static QString TextFrame;
 	static QString LatexFrame;
Index: scribus/hruler.cpp
===================================================================
--- scribus/hruler.cpp	(wersja 17243)
+++ scribus/hruler.cpp	(kopia robocza)
@@ -34,6 +34,7 @@
 #include "canvasgesture_rulermove.h"
 #include "hruler.h"
 #include "page.h"
+#include "pageitem_textframe.h"
 #include "prefsmanager.h"
 #include "scribus.h"
 #include "scribusdoc.h"
@@ -241,14 +242,17 @@
 		{
 			bool mustApplyStyle = false;
 			ParagraphStyle paraStyle;
-			double ColWidth = (textWidth() - ColGap * (Cols - 1)) / Cols;			
+			double ColWidth = (textWidth() - ColGap * (Cols - 1)) / Cols;
+			exactlyTextEditAct ETEA = ETEAsetIndentMargs;
 			switch (RulerCode)
 			{
 				case rc_leftFrameDist:
+					currDoc->m_Selection->itemAt(0)->setUndoColsGapDist(Cols, ColGap, Extra, RExtra, currDoc->m_Selection->itemAt(0)->textToFrameDistTop(), currDoc->m_Selection->itemAt(0)->textToFrameDistBottom());
 					currDoc->m_Selection->itemAt(0)->setTextToFrameDistLeft(Extra);
 					emit DocChanged(false);
 					break;
 				case rc_rightFrameDist:
+					currDoc->m_Selection->itemAt(0)->setUndoColsGapDist(Cols, ColGap, Extra, RExtra, currDoc->m_Selection->itemAt(0)->textToFrameDistTop(), currDoc->m_Selection->itemAt(0)->textToFrameDistBottom());
 					currDoc->m_Selection->itemAt(0)->setTextToFrameDistRight(RExtra);
 					emit DocChanged(false);
 					break;
@@ -269,6 +273,7 @@
 					emit DocChanged(false);
 					break;
 				case rc_tab:
+					ETEA = ETEAmanageTabs;
 					if (m->button() == Qt::RightButton)
 					{
 						TabValues[ActTab].tabType += 1;
@@ -284,9 +289,11 @@
 			}
 			if (mustApplyStyle)
 			{
+				currItem->itemTextSaxed = currItem->getItemTextSaxed(PageItem::PARAGRAPH);
 				Selection tempSelection(this, false);
 				tempSelection.addItem(currItem);
 				currDoc->itemSelection_ApplyParagraphStyle(paraStyle, &tempSelection);
+				currItem->asTextFrame()->updateUndo(PageItem::PARAGRAPH, ETEA);
 			}
 			else
 			{
@@ -303,7 +310,9 @@
 				paraStyle.setTabValues(TabValues);
 				Selection tempSelection(this, false);
 				tempSelection.addItem(currItem);
+				currItem->itemTextSaxed = currItem->getItemTextSaxed(PageItem::PARAGRAPH);
 				currDoc->itemSelection_ApplyParagraphStyle(paraStyle, &tempSelection);
+				currItem->asTextFrame()->updateUndo(PageItem::PARAGRAPH, ETEAmanageTabs);
 				emit DocChanged(false);
 				qApp->changeOverrideCursor(QCursor(Qt::ArrowCursor));
 			}
Index: scribus/charselect.cpp
===================================================================
--- scribus/charselect.cpp	(wersja 17243)
+++ scribus/charselect.cpp	(kopia robocza)
@@ -113,7 +113,7 @@
 	{
 		m_Item->itemTextSaxed = m_Item->getItemTextSaxed(PageItem::SELECTION);
 		m_Item->asTextFrame()->deleteSelectedTextFromFrame();
-		m_Item->asTextFrame()->lastUndoAction = PageItem::NOACTION;
+		m_Item->asTextFrame()->clearLastUndoAction();
 	}
 	if (m_Item->asTextFrame())
 		m_Item->asTextFrame()->invalidateLayout();
@@ -132,9 +132,9 @@
 		txtIns.append(ch);
 	}
 	if (m_Item->itemTextSaxed.isEmpty())
-		m_Item->asTextFrame()->updateUndo(PageItem::INS, txtIns);
+		m_Item->asTextFrame()->updateUndo(PageItem::INS, ETEAinsertingSpecChar, txtIns);
 	else
-		m_Item->asTextFrame()->updateUndo(PageItem::REPSAX, m_Item->getTextSaxed(txtIns));
+		m_Item->asTextFrame()->updateUndo(PageItem::REPSAX, ETEAinsertingSpecChar, m_Item->getTextSaxed(txtIns));
 	m_doc->updateFrameItems();
 	m_doc->view()->DrawNew();
 	m_doc->changed();
@@ -149,7 +149,7 @@
 	{
 		m_Item->itemTextSaxed = m_Item->getItemTextSaxed(PageItem::SELECTION);
 		m_Item->asTextFrame()->deleteSelectedTextFromFrame();
-		m_Item->asTextFrame()->lastUndoAction = PageItem::NOACTION;
+		m_Item->asTextFrame()->clearLastUndoAction();
 	}
 	if (m_Item->asTextFrame())
 		m_Item->asTextFrame()->invalidateLayout();
@@ -161,9 +161,9 @@
 	m_Item->oldCPos = m_Item->itemText.cursorPosition();
 	m_Item->itemText.insertChars(ch, true);
 	if (m_Item->itemTextSaxed.isEmpty())
-		m_Item->asTextFrame()->updateUndo(PageItem::INS, QString(ch));
+		m_Item->asTextFrame()->updateUndo(PageItem::INS, ETEAinsertingSpecChar, QString(ch));
 	else
-		m_Item->asTextFrame()->updateUndo(PageItem::REPSAX, m_Item->getTextSaxed(QString(ch)));
+		m_Item->asTextFrame()->updateUndo(PageItem::REPSAX, ETEAinsertingSpecChar, m_Item->getTextSaxed(QString(ch)));
 	m_doc->updateFrameItems();
 	m_doc->view()->DrawNew();
 	m_doc->changed();
Index: scribus/canvasmode_edit.cpp
===================================================================
--- scribus/canvasmode_edit.cpp	(wersja 17243)
+++ scribus/canvasmode_edit.cpp	(kopia robocza)
@@ -410,7 +410,7 @@
 	PageItem *currItem = 0;
 	if (GetItem(&currItem) && (m_doc->appMode == modeEdit) && currItem->asTextFrame())
 	{
-		currItem->asTextFrame()->lastUndoAction = PageItem::NOACTION;
+		currItem->asTextFrame()->clearLastUndoAction();
 		//CB if annotation, open the annotation dialog
 		if (currItem->isAnnotation())
 		{
@@ -650,7 +650,7 @@
 					if (currItem->asTextFrame())
 					{
 						m_view->slotSetCurs(m->globalPos().x(), m->globalPos().y());
-						currItem->asTextFrame()->lastUndoAction = PageItem::NOACTION;
+						currItem->asTextFrame()->clearLastUndoAction();
 					}
 				}
 				else
@@ -668,7 +668,7 @@
 		//CB Where we set the cursor for a click in text frame
 		if (currItem->asTextFrame())
 		{
-			currItem->asTextFrame()->lastUndoAction = PageItem::NOACTION;
+			currItem->asTextFrame()->clearLastUndoAction();
 			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)
@@ -678,7 +678,7 @@
 				//m_view->slotDoCurs(true);
 				m_view->requestMode(modeNormal);
 				if (currItem->isTextFrame())
-					currItem->asTextFrame()->lastUndoAction = PageItem::NOACTION;
+					currItem->asTextFrame()->clearLastUndoAction();
 				return;
 			}
 
@@ -703,7 +703,7 @@
 							oldP = currItem->itemText.endOfSelection();
 						}
 						currItem->asTextFrame()->itemText.extendSelection(oldP, currItem->itemText.cursorPosition());
-						currItem->asTextFrame()->lastUndoAction = PageItem::NOACTION;
+						currItem->asTextFrame()->clearLastUndoAction();
 						oldCp = currItem->itemText.cursorPosition();
 					}
 					else
@@ -719,7 +719,7 @@
 								currItem->itemText.setCursorPosition( currItem->itemText.startOfParagraph() );
 						}
 						currItem->asTextFrame()->ExpandSel(dir, oldP);
-						currItem->asTextFrame()->lastUndoAction = PageItem::NOACTION;
+						currItem->asTextFrame()->clearLastUndoAction();
 						oldCp = oldP;
 					}
 				}
@@ -727,7 +727,7 @@
 				{
 					oldCp = currItem->itemText.cursorPosition();
 					currItem->itemText.deselectAll();
-					currItem->asTextFrame()->lastUndoAction = PageItem::NOACTION;
+					currItem->asTextFrame()->clearLastUndoAction();
 					currItem->HasSel = false;
 				}
 				currItem->emitAllToGUI();
@@ -744,7 +744,7 @@
 						// K.I.S.S.:
 						currItem->oldCPos = 0;
 						currItem->itemText.insertChars(0, cc, true);
-						currItem->asTextFrame()->updateUndo(PageItem::INS,cc);
+						currItem->asTextFrame()->updateUndo(PageItem::INS, ETEAinsertingText, cc);
 						if (m_doc->docHyphenator->AutoCheck)
 							m_doc->docHyphenator->slotHyphenate(currItem);
 						m_ScMW->BookMarkTxT(currItem);
Index: scribus/pageitem.h
===================================================================
--- scribus/pageitem.h	(wersja 17243)
+++ scribus/pageitem.h	(kopia robocza)
@@ -170,21 +170,15 @@
 	//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)
+		STORY = 0,
+		PARAGRAPH = 1,
+		SELECTION = 2,
+		DELSAX = 3,	//delete with styles
+		INSSAX = 4,	//insert with styles
+		REPSAX = 5,	//replace with styles
+		INS = 6		//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; }
@@ -474,7 +468,7 @@
   // for itemText undo purpose
 	int oldCPos;
 	QString itemTextSaxed;
-	QString getItemTextSaxed(EditActPlace undoItem);
+	QString getItemTextSaxed(EditAct action);
 	QString getItemTextSaxed(int selStart, int selLength);
 	QString getTextSaxed(QString str);
   /** Flag fuer PDF-Bookmark */
@@ -657,12 +651,18 @@
 	void setTextToFrameDistRight(double);
 	void setTextToFrameDistTop(double);
 	void setTextToFrameDistBottom(double);
+
+	// sets columns, gaps and text distances and create undo step invoking setUndoColsGapDist
+	void setColsGapDist(int newCols, double newGap, double newLeft, double newRight, double newTop, double newBottom);
+	void setUndoColsGapDist(int newCols, double newGap, double newLeft, double newRight, double newTop, double newBottom);
+
 	void setColumns(int);
 	void setColumnGap(double);
 	void setGridOffset(double);
 	void setGridDistance(double);
 	FirstLineOffsetPolicy firstLineOffset()const;
 	void setFirstLineOffset(FirstLineOffsetPolicy);
+	void setUndoFirstLineOffset(FirstLineOffsetPolicy);
 	/**
 	 * \brief Set the text to frame distances all at once
 	 * @param newLeft left distance
@@ -1076,7 +1076,7 @@
 	void restoreArrow(SimpleState *state, bool isUndo, bool isStart);
 
 	void restorePStyle(SimpleState *state, bool isUndo);
-
+	void restoreColsGapDist(SimpleState *state, bool isUndo);
 	void restoreType(SimpleState *state, bool isUndo);
 	void restoreTextFlowing(SimpleState *state, bool isUndo);
 	void restoreImageScaleMode(SimpleState *state, bool isUndo);
@@ -1095,6 +1095,7 @@
 	void restoreEditText(SimpleState *state, bool isUndo);
 	void restoreLinkTextFrame(UndoState *state, bool isUndo);
 	void restoreUnlinkTextFrame(UndoState *state, bool isUndo);
+	void restoreFirstLineOffset(SimpleState *state, bool isUndo);
 	void restoreReverseText(UndoState *state, bool isUndo);
 	/*@}*/
 
Index: scribus/scribusstructs.h
===================================================================
--- scribus/scribusstructs.h	(wersja 17243)
+++ scribus/scribusstructs.h	(kopia robocza)
@@ -472,6 +472,53 @@
 	}
 };
 
+
+//ETEA = Exactly Text Edit Action
+//for Undo state comparising and detailed description
+typedef enum {
+	ETEAotherEditAction,
+	ETEAsetLineSpacingMode,
+	ETEAsetOpticalMargins,
+	ETEAsetMinWordTracking,
+	ETEAsetNormWordTracking,
+	ETEAsetMinGlyphExtension,
+	ETEAsetMaxGlyphExtension,
+	ETEAnewTScaleV,
+	ETEAnewTBase,
+	ETEAnewTScale,
+	ETEAnewLineSpacing,
+	ETEAnewSize,
+	ETEAnewTracking,
+	ETEAnewAlignement,
+	ETEAsetTypeStyle,
+	ETEAnewShadowOffs,
+	ETEAnewUnderline,
+	ETEAnewStrike,
+	ETEAnewOutlineW,
+	ETEAclearCStyle,
+	ETEAclearPStyle,
+	ETEAnewTxtFill,
+	ETEAnewTxtStroke,
+	ETEAsetActShade,
+	ETEAmanageTabs,
+	ETEAsetNewFont,
+	ETEAsetItemFSize,
+	ETEAsetItemShade,
+	ETEAsetNewParStyle,
+	ETEAsetNewCharStyle,
+	ETEAclearContents,
+	ETEAgetContent,
+	ETEAfileAppend,
+	ETEAinsertingText,
+	ETEAinsertingSpecChar,
+	ETEAinsertLoremIpsum,
+	ETEAreplacingText,
+	ETEAdeletingText,
+	ETEAdeletingBackText,
+	ETEAsetColsGapDist,
+	ETEAsetIndentMargs,
+	ETEAsetFirstLineOffset
+} exactlyTextEditAct;
+
 #endif
 
-
Index: scribus/actionmanager.cpp
===================================================================
--- scribus/actionmanager.cpp	(wersja 17243)
+++ scribus/actionmanager.cpp	(kopia robocza)
@@ -94,9 +94,59 @@
 	initUnicodeActions(scrActions, mainWindow, unicodeCharActionNames);
 	enableUnicodeActions(scrActions, false);
 	initSpecialActions();
-	
+	initTextEditActionsDescriptions();
+
 }
 
+void ActionManager::initTextEditActionsDescriptions()
+{
+	textEditActionDescriptions.clear();
+	textEditActionDescriptions.insert(ETEAotherEditAction, QObject::tr("Other action"));
+	textEditActionDescriptions.insert(ETEAsetLineSpacingMode, QObject::tr("Set line spacing mode"));
+	textEditActionDescriptions.insert(ETEAsetOpticalMargins, QObject::tr("Set optical margins"));
+	textEditActionDescriptions.insert(ETEAsetMinWordTracking, QObject::tr("Set min word tracking"));
+	textEditActionDescriptions.insert(ETEAsetNormWordTracking, QObject::tr("Set normla word tracking"));
+	textEditActionDescriptions.insert(ETEAsetMinGlyphExtension, QObject::tr("Set min glyph extension"));
+	textEditActionDescriptions.insert(ETEAsetMaxGlyphExtension, QObject::tr("Set max glyph extension"));
+	textEditActionDescriptions.insert(ETEAnewTScaleV, QObject::tr("Set T scale V"));
+	textEditActionDescriptions.insert(ETEAnewTBase, QObject::tr("Set T base"));
+	textEditActionDescriptions.insert(ETEAnewTScale, QObject::tr("Set T scale"));
+	textEditActionDescriptions.insert(ETEAnewLineSpacing, QObject::tr("Set line spacing"));
+	textEditActionDescriptions.insert(ETEAnewSize, QObject::tr("Set size"));
+	textEditActionDescriptions.insert(ETEAnewTracking, QObject::tr("Set tracking"));
+	textEditActionDescriptions.insert(ETEAnewAlignement, QObject::tr("Apply alignment"));
+	textEditActionDescriptions.insert(ETEAsetTypeStyle, QObject::tr("Set text effects"));
+	textEditActionDescriptions.insert(ETEAnewShadowOffs, QObject::tr("Set shadow offset"));
+	textEditActionDescriptions.insert(ETEAnewUnderline, QObject::tr("Set underline"));
+	textEditActionDescriptions.insert(ETEAnewStrike, QObject::tr("Set strike"));
+	textEditActionDescriptions.insert(ETEAnewOutlineW, QObject::tr("Set outline"));
+	textEditActionDescriptions.insert(ETEAclearCStyle, QObject::tr("Clear character formatting"));
+	textEditActionDescriptions.insert(ETEAclearPStyle, QObject::tr("Clear paragraph style"));
+	textEditActionDescriptions.insert(ETEAnewTxtFill, QObject::tr("Set fill color"));
+	textEditActionDescriptions.insert(ETEAnewTxtStroke, QObject::tr("Set text stroke"));
+	textEditActionDescriptions.insert(ETEAsetActShade, QObject::tr("Set shade"));
+	textEditActionDescriptions.insert(ETEAmanageTabs, QObject::tr("Manage tabs"));
+	textEditActionDescriptions.insert(ETEAsetNewFont, QObject::tr("Set font name"));
+	textEditActionDescriptions.insert(ETEAsetItemFSize, QObject::tr("Set font size"));
+	textEditActionDescriptions.insert(ETEAsetItemShade, QObject::tr("Apply shade"));
+	textEditActionDescriptions.insert(ETEAsetNewParStyle, QObject::tr("Apply paragraph style"));
+	textEditActionDescriptions.insert(ETEAsetNewCharStyle, QObject::tr("Apply character style"));
+	textEditActionDescriptions.insert(ETEAclearContents, QObject::tr("Clear contents"));
+	textEditActionDescriptions.insert(ETEAgetContent, QObject::tr("Load text file"));
+	textEditActionDescriptions.insert(ETEAfileAppend, QObject::tr("Append text file"));
+	textEditActionDescriptions.insert(ETEAinsertingText, QObject::tr("Inserting text"));
+	textEditActionDescriptions.insert(ETEAinsertingSpecChar, QObject::tr("Inserting special char"));
+	textEditActionDescriptions.insert(ETEAinsertLoremIpsum, QObject::tr("Inserting text example"));
+	textEditActionDescriptions.insert(ETEAreplacingText, QObject::tr("Replacing text"));
+	textEditActionDescriptions.insert(ETEAdeletingText, QObject::tr("Deleting text"));
+	textEditActionDescriptions.insert(ETEAdeletingBackText, QObject::tr("Deleting text backward"));
+	// better merge it with "ManageTabs"
+	//textEditActionDescriptions.insert(ETEAinsertingTabs, QObject::tr("Inserting Tabs"));
+	textEditActionDescriptions.insert(ETEAsetColsGapDist, QObject::tr("Manage columns, gaps, distances"));
+	textEditActionDescriptions.insert(ETEAsetIndentMargs, QObject::tr("Manage indents and margins"));
+	textEditActionDescriptions.insert(ETEAsetFirstLineOffset, QObject::tr("Set first line offset"));
+}
+
 void ActionManager::initFileMenuActions()
 {
 	QString name;
@@ -1503,6 +1553,7 @@
 	(*scrActions)["specialUnicodeSequenceBegin"]->setTexts( tr("Insert Unicode Character Begin Sequence"));
 	languageChangeUnicodeActions(scrActions);
 	languageChangeActions();
+	initTextEditActionsDescriptions();
 }
 
 void ActionManager::languageChangeUnicodeActions(QMap<QString, QPointer<ScrAction> > *actionMap)
Index: scribus/pageitem_textframe.h
===================================================================
--- scribus/pageitem_textframe.h	(wersja 17243)
+++ scribus/pageitem_textframe.h	(kopia robocza)
@@ -34,6 +34,7 @@
 class ScribusDoc;
 
 #include "text/nlsconfig.h"
+#include "scribusstructs.h"
 
 #ifdef NLS_PROTO
 #include "text/sctextengine.h"
@@ -66,8 +67,8 @@
 	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 expandParaSelection(bool includeEOL = false);
+	void restoreTextSelection(int selStart, int selLength);
 	void deselectAll();
 	
 	virtual void invalidateLayout();
@@ -105,12 +106,20 @@
 	bool cursorBiasBackward;
 
 	void setShadow();
-	void restoreTextSelection(int selStart, int selLength);
 	QString currentShadow;
 	QMap<QString,StoryText> shadows;
+
+	EditAct lastUndoAction;
+	exactlyTextEditAct lastExactTextEditAction;
+	
 public:
-	void updateUndo(EditAct action = PARAMFULL, QString str = "");
-	EditAct lastUndoAction;
+	void clearLastUndoAction() { lastUndoAction = PageItem::NOACTION; }
+	EditAct getLastUndoAction() { return lastUndoAction; }
+	exactlyTextEditAct getLastETEA() { return lastExactTextEditAction; }
+	void setLastUndoAction(EditAct action) { lastUndoAction = action; }
+	void setLastETEA(exactlyTextEditAct ETEA) { lastExactTextEditAction = ETEA; }
+	void updateUndo(EditAct action, exactlyTextEditAct newAction, QString str = "");
+	void updateUndo(EditAct action, QString str = "") { updateUndo(action, ETEAotherEditAction, str); }
 private slots:
 	void slotInvalidateLayout();
 };
