r24265 by jghali - #16343: Scribus crashes when copy/pasting text if style is not in target document

scribus-commit scribus-commit at lists.scribus.net
Fri Nov 20 14:36:20 UTC 2020


Author: jghali
Date: Fri Nov 20 14:36:20 2020
New Revision: 24265

URL: http://scribus.net/websvn/listing.php?repname=Scribus&sc=1&rev=24265
Log:
#16343: Scribus crashes when copy/pasting text if style is not in target document

Added:
    trunk/Scribus/scribus/storyloader.cpp
    trunk/Scribus/scribus/storyloader.h
Modified:
    trunk/Scribus/scribus/CMakeLists.txt
    trunk/Scribus/scribus/loadsaveplugin.cpp
    trunk/Scribus/scribus/loadsaveplugin.h
    trunk/Scribus/scribus/plugins/fileloader/scribus150format/scribus150format.cpp
    trunk/Scribus/scribus/plugins/fileloader/scribus150format/scribus150format.h
    trunk/Scribus/scribus/plugins/fileloader/scribus150format/scribus150format_save.cpp
    trunk/Scribus/scribus/sccolor.h
    trunk/Scribus/scribus/scribus.cpp
    trunk/Scribus/scribus/scribusdoc.cpp
    trunk/Scribus/scribus/scribusdoc.h
    trunk/Scribus/scribus/scxmlstreamwriter.h
    trunk/Scribus/scribus/styles/charstyle.cpp
    trunk/Scribus/scribus/styles/paragraphstyle.cpp
    trunk/Scribus/scribus/text/storytext.cpp
    trunk/Scribus/scribus/text/storytext.h
    trunk/Scribus/win32/msvc2015/scribus-main/Scribus.vcxproj
    trunk/Scribus/win32/msvc2015/scribus-main/Scribus.vcxproj.filters
    trunk/Scribus/win32/msvc2017/scribus-main/Scribus.vcxproj
    trunk/Scribus/win32/msvc2017/scribus-main/Scribus.vcxproj.filters
    trunk/Scribus/win32/msvc2019/scribus-main/Scribus.vcxproj
    trunk/Scribus/win32/msvc2019/scribus-main/Scribus.vcxproj.filters

Modified: trunk/Scribus/scribus/CMakeLists.txt
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=24265&path=/trunk/Scribus/scribus/CMakeLists.txt
==============================================================================
--- trunk/Scribus/scribus/CMakeLists.txt	(original)
+++ trunk/Scribus/scribus/CMakeLists.txt	Fri Nov 20 14:36:20 2020
@@ -316,6 +316,7 @@
 	scribuswin.h
 	selection.h
 	selectionrubberband.h
+	storyloader.h
 	styleitem.h
 	tocgenerator.h
 	undogui.h
@@ -774,6 +775,7 @@
 	selection.cpp
 	selectionrubberband.cpp
 	serializer.cpp
+	storyloader.cpp
 	styleitem.cpp
 	tableborder.cpp
 	tablecell.cpp

Modified: trunk/Scribus/scribus/loadsaveplugin.cpp
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=24265&path=/trunk/Scribus/scribus/loadsaveplugin.cpp
==============================================================================
--- trunk/Scribus/scribus/loadsaveplugin.cpp	(original)
+++ trunk/Scribus/scribus/loadsaveplugin.cpp	Fri Nov 20 14:36:20 2020
@@ -424,6 +424,16 @@
 	return QImage();
 }
 
+bool LoadSavePlugin::loadStory(const QByteArray& /*data*/, StoryText& /*story*/, PageItem* /*item*/)
+{
+	return false;
+}
+
+bool LoadSavePlugin::saveStory(StoryText& /*story*/, PageItem* /*item*/, QByteArray& /*data*/)
+{
+	return false;
+}
+
 bool FileFormat::loadFile(const QString & fileName, int flags, int index) const
 {
 	if (plug && load)
@@ -545,5 +555,12 @@
 	return (plug && load && thumb) ? plug->readThumbnail(fileName) : QImage();
 }
 
-
-
+bool  FileFormat::loadStory(const QByteArray& data, StoryText& story, PageItem* item) const
+{
+	return (plug && load) ? plug->loadStory(data, story, item) : false;
+}
+
+bool  FileFormat::saveStory(StoryText& story, PageItem* item, QByteArray& data) const
+{
+	return plug ? plug->saveStory(story, item, data) : false;
+}

Modified: trunk/Scribus/scribus/loadsaveplugin.h
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=24265&path=/trunk/Scribus/scribus/loadsaveplugin.h
==============================================================================
--- trunk/Scribus/scribus/loadsaveplugin.h	(original)
+++ trunk/Scribus/scribus/loadsaveplugin.h	Fri Nov 20 14:36:20 2020
@@ -89,6 +89,10 @@
 		virtual bool savePalette(const QString & fileName);
 		virtual QString saveElements(double, double, double, double, Selection*, QByteArray &prevData);
 
+		// Save requested item story
+		virtual bool loadStory(const QByteArray& data, StoryText& story, PageItem* item);
+		virtual bool saveStory(StoryText& story, PageItem* item, QByteArray& data);
+
 		// Return last file saved, this may be the last fileName argument passed to saveFile(),
 		// a temporary file name or an empty string if last call to saveFile() could not create
 		// a valid file
@@ -100,6 +104,9 @@
 		// file type (eg "XML doc with root element SCRIBUSXML and version 1.3.1").
 		// All plugins must implement this method.
 		virtual bool fileSupported(QIODevice* file, const QString & fileName=QString()) const = 0;
+
+		// Examine if the passed story data to see whether it appears to be loadable with this plugin
+		virtual bool storySupported(const QByteArray& storyData) const { return false; }
 
 		// Return a list of all formats supported by all currently loaded and
 		// active plugins. This list is sorted in a very specific order:
@@ -196,13 +203,20 @@
 		FileFormat(LoadSavePlugin * plug);
 
 		bool loadElements(const QString & data, const QString& fileDir, int toLayer, double Xp_in, double Yp_in, bool loc) const;
+
 		// Load a file with this format
 		bool loadFile(const QString & fileName, int flags, int index = 0) const;
 		bool loadPalette(const QString & fileName) const;
+
 		// Save a file with this format
 		bool saveFile(const QString & fileName) const;
 		bool savePalette(const QString & fileName) const;
 		QString saveElements(double xp, double yp, double wp, double hp, Selection* selection, QByteArray &prevData) const;
+
+		// Save item story with this format
+		bool loadStory(const QByteArray& data, StoryText& story, PageItem* item) const;
+		bool saveStory(StoryText& story, PageItem* item, QByteArray& data) const;
+
 		// Get last saved file
 		QString lastSavedFile() const;
 
@@ -215,6 +229,7 @@
 		bool readColors(const QString& fileName, ColorList & colors) const;
 		bool readPageCount(const QString& fileName, int *num1, int *num2, QStringList & masterPageNames) const;
 		QImage readThumbnail(const QString& fileName) const;
+
 		//
 		// Data members
 		//

Modified: trunk/Scribus/scribus/plugins/fileloader/scribus150format/scribus150format.cpp
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=24265&path=/trunk/Scribus/scribus/plugins/fileloader/scribus150format/scribus150format.cpp
==============================================================================
--- trunk/Scribus/scribus/plugins/fileloader/scribus150format/scribus150format.cpp	(original)
+++ trunk/Scribus/scribus/plugins/fileloader/scribus150format/scribus150format.cpp	Fri Nov 20 14:36:20 2020
@@ -152,6 +152,18 @@
 	return false;
 }
 
+bool Scribus150Format::storySupported(const QByteArray& storyData) const
+{
+	QRegExp regExp150("Version=\"1.5.[0-9]");
+	int startElemPos = storyData.left(512).indexOf("<ScribusStory ");
+	if (startElemPos >= 0)
+	{
+		bool is150 = (regExp150.indexIn(storyData.mid(startElemPos, 64)) >= 0);
+		return is150;
+	}
+	return false;
+}
+
 QIODevice* Scribus150Format::slaReader(const QString & fileName)
 {
 	if (!fileSupported(nullptr, fileName))
@@ -732,11 +744,190 @@
 	return true;
 }
 
+bool Scribus150Format::loadStory(const QByteArray& data, StoryText& story, PageItem* item)
+{
+	ParagraphStyle vg;
+	isNewFormat = false;
+
+	itemRemap.clear();
+	itemNext.clear();
+	itemCount = 0;
+	itemRemapM.clear();
+	itemNextM.clear();
+	itemCountM = 0;
+	itemRemapF.clear();
+	itemNextF.clear();
+	FrameItems.clear();
+	LinkID.clear();
+
+	markeredItemsMap.clear();
+	markeredMarksMap.clear();
+	nsetRangeItemNamesMap.clear();
+	notesFramesData.clear();
+	notesMasterMarks.clear();
+	notesNSets.clear();
+
+	bool firstElement = true;
+	bool success = true;
+
+	ReadObjectParams readObjectParams;
+	readObjectParams.baseDir = QString() /*fileDir*/; //FIXME
+	readObjectParams.itemKind = PageItem::InlineItem;
+	readObjectParams.loadingPage = true;
+
+	ScXmlStreamReader reader(data);
+	ScXmlStreamAttributes attrs;
+	while (!reader.atEnd() && !reader.hasError())
+	{
+		QXmlStreamReader::TokenType tType = reader.readNext();
+		if (tType != QXmlStreamReader::StartElement)
+			continue;
+		QStringRef tagName = reader.name();
+		attrs = reader.scAttributes();
+
+		if (firstElement)
+		{
+			if (tagName != "ScribusStory")
+			{
+				success = false;
+				break;
+			}
+			firstElement = false;
+		}
+
+		// 10/25/2004 pv - None is "reserved" color. cannot be defined in any file...
+		if (tagName == "COLOR" && attrs.valueAsString("NAME") != CommonStrings::None)
+		{
+			QString colorName = attrs.valueAsString("NAME");
+			if (m_Doc->PageColors.contains(colorName))
+				continue;
+			readColor(m_Doc->PageColors, attrs);
+		}
+		if (tagName == "Gradient")
+		{
+			VGradient gra;
+			QString grName = attrs.valueAsString("Name");
+			success = readGradient(m_Doc, gra, reader);
+			if (!success)
+				break;
+			gra.setRepeatMethod((VGradient::VGradientRepeatMethod)(attrs.valueAsInt("Ext", VGradient::pad)));
+			if (!grName.isEmpty() && !m_Doc->docGradients.contains(grName))
+				m_Doc->docGradients.insert(grName, gra);
+		}
+		if (tagName == "STYLE")
+		{
+			readParagraphStyle(m_Doc, reader, vg);
+			// FIXME: import style under new name if existing
+			// Do not break current doc for now
+			if (m_Doc->paragraphStyles().contains(vg.name()))
+				continue;
+			StyleSet<ParagraphStyle> tmp;
+			tmp.create(vg);
+			m_Doc->redefineStyles(tmp, false);
+		}
+		if (tagName == "CHARSTYLE")
+		{
+			CharStyle cstyle;
+			ScXmlStreamAttributes attrs = reader.scAttributes();
+			readNamedCharacterStyleAttrs(m_Doc, attrs, cstyle);
+			// FIXME: import style under new name if existing
+			// Do not break current doc for now
+			if (m_Doc->charStyles().contains(cstyle.name()))
+				continue;
+			StyleSet<CharStyle> temp;
+			temp.create(cstyle);
+			m_Doc->redefineCharStyles(temp, false);
+		}
+		if (tagName == "TableStyle")
+		{
+			TableStyle tstyle;
+			readTableStyle(m_Doc, reader, tstyle);
+			// FIXME: import style under new name if existing
+			// Do not break current doc for now
+			if (m_Doc->tableStyles().contains(tstyle.name()))
+				continue;
+			StyleSet<TableStyle> temp;
+			temp.create(tstyle);
+			m_Doc->redefineTableStyles(temp, false);
+		}
+		if (tagName == "CellStyle")
+		{
+			CellStyle tstyle;
+			readCellStyle(m_Doc, reader, tstyle);
+			// FIXME: import style under new name if existing
+			// Do not break current doc for now
+			if (m_Doc->cellStyles().contains(tstyle.name()))
+				continue;
+			StyleSet<CellStyle> temp;
+			temp.create(tstyle);
+			m_Doc->redefineCellStyles(temp, false);
+		}
+		if (tagName == "Arrows")
+		{
+			success = readArrows(m_Doc, attrs);
+			if (!success) break;
+		}
+		if (tagName == "MultiLine")
+		{
+			multiLine ml;
+			QString mlName = attrs.valueAsString("Name");
+			success = readMultiline(ml, reader);
+			if (!success)
+				break;
+			if (!mlName.isEmpty() && !m_Doc->docLineStyles.contains(mlName))
+				m_Doc->docLineStyles.insert(mlName, ml);
+		}
+		if (tagName == "FRAMEOBJECT")
+		{
+			ItemInfo itemInfo;
+			success = readObject(m_Doc, reader, readObjectParams, itemInfo);
+			if (!success)
+				break;
+			itemInfo.item->m_layerID = LayerToPaste;
+		}
+		if (tagName == "StoryText")
+		{
+			readStoryText(m_Doc, reader, story, item);
+		}
+		if (tagName == "Pattern") // FIXME
+		{
+			/*success = readPattern(m_Doc, reader, fileDir);
+			if (!success) break;*/
+		}
+		if (tagName == "NotesStyles")
+		{
+			success = readNotesStyles(m_Doc, reader);
+			if (!success) break;
+		}
+		if (tagName == "Notes")
+		{
+			success = readNotes(m_Doc, reader);
+			if (!success) break;
+		}
+		if (tagName == "Marks")
+		{
+			success = readMarks(m_Doc, reader);
+			if (!success) break;
+		}
+	}
+
+	if (reader.hasError())
+	{
+		setDomParsingError(reader.errorString(), reader.lineNumber(), reader.columnNumber());
+		return false;
+	}
+
+	//update names to pointers
+	updateNames2Ptr();
+
+	return true;
+}
+
 bool Scribus150Format::loadPalette(const QString & fileName)
 {
-	if (m_Doc==nullptr || m_AvailableFonts==nullptr)
-	{
-		Q_ASSERT(m_Doc==nullptr || m_AvailableFonts==nullptr);
+	if (m_Doc == nullptr || m_AvailableFonts == nullptr)
+	{
+		Q_ASSERT(m_Doc == nullptr || m_AvailableFonts == nullptr);
 		return false;
 	}
 	ParagraphStyle vg;
@@ -3234,7 +3425,8 @@
 		fp >> ya;
 		arrow.points.addPoint(xa, ya);
 	}
-	doc->appendToArrowStyles(arrow);
+	if (!doc->hasArrowStyle(arrow.name))
+		doc->appendToArrowStyles(arrow);
 	return true;
 }
 
@@ -4045,7 +4237,7 @@
 		}
 
 		if (tName == "ITEXT")
-			readItemText(newItem, tAtt, lastStyle);
+			readItemText(newItem->itemText, tAtt, lastStyle);
 		else if (tName == "TableData")
 		{
 			readItemTableData(newItem->asTable(), reader, doc);
@@ -4191,7 +4383,7 @@
 			newItem->effectsInUse.append(ef);
 		}
 		if (tName == "StoryText")
-			readStoryText(doc, reader, newItem);
+			readStoryText(doc, reader, newItem->itemText, newItem);
 		if (tName == "Tabs")
 		{
 			ParagraphStyle::TabRecord tb;
@@ -4652,7 +4844,7 @@
 	return success;
 }
 
-bool Scribus150Format::readStoryText(ScribusDoc *doc, ScXmlStreamReader& reader, PageItem* item)
+bool Scribus150Format::readStoryText(ScribusDoc *doc, ScXmlStreamReader& reader, StoryText& story, PageItem* item)
 {
 	QStringRef tagName = reader.name();
 	ScXmlStreamAttributes attrs = reader.scAttributes();
@@ -4672,86 +4864,86 @@
 		{
 			ParagraphStyle newStyle;
 			readParagraphStyle(doc, reader, newStyle);
-			item->itemText.setDefaultStyle(newStyle);
+			story.setDefaultStyle(newStyle);
 		}
 
 		if (tName == "ITEXT")
-			readItemText(item, tAtt, lastStyle);
+			readItemText(story, tAtt, lastStyle);
 		else if (tName == "para")
 		{
-			item->itemText.insertChars(item->itemText.length(), SpecialChars::PARSEP);
+			story.insertChars(story.length(), SpecialChars::PARSEP);
 			ParagraphStyle newStyle;
 			readParagraphStyle(doc, reader, newStyle);
-			item->itemText.setStyle(item->itemText.length()-1, newStyle);
-			item->itemText.setCharStyle(item->itemText.length()-1, 1, lastStyle->Style);
+			story.setStyle(story.length() - 1, newStyle);
+			story.setCharStyle(story.length() - 1, 1, lastStyle->Style);
 		}
 		else if (tName == "trail")
 		{
 			ParagraphStyle newStyle;
 			readParagraphStyle(doc, reader, newStyle);
-			item->itemText.setStyle(item->itemText.length(), newStyle);
+			story.setStyle(story.length(), newStyle);
 		}
 		else if (tName == "tab")
 		{
 			CharStyle newStyle;
-			item->itemText.insertChars(item->itemText.length(), SpecialChars::TAB);
+			story.insertChars(story.length(), SpecialChars::TAB);
 			readCharacterStyleAttrs(doc, tAtt, newStyle);
-			item->itemText.setCharStyle(item->itemText.length()-1, 1, newStyle);
-			lastStyle->StyleStart = item->itemText.length()-1;
+			story.setCharStyle(story.length() - 1, 1, newStyle);
+			lastStyle->StyleStart = story.length() - 1;
 			lastStyle->Style = newStyle;
 		}
 		else if (tName == "breakline")
-			item->itemText.insertChars(item->itemText.length(), SpecialChars::LINEBREAK);
+			story.insertChars(story.length(), SpecialChars::LINEBREAK);
 		else if (tName == "breakcol")
-			item->itemText.insertChars(item->itemText.length(), SpecialChars::COLBREAK);
+			story.insertChars(story.length(), SpecialChars::COLBREAK);
 		else if (tName == "breakframe")
-			item->itemText.insertChars(item->itemText.length(), SpecialChars::FRAMEBREAK);
+			story.insertChars(story.length(), SpecialChars::FRAMEBREAK);
 		else if (tName == "nbhyphen")
 		{
 			CharStyle newStyle;
-			item->itemText.insertChars(item->itemText.length(), SpecialChars::NBHYPHEN);
+			story.insertChars(story.length(), SpecialChars::NBHYPHEN);
 			readCharacterStyleAttrs(doc, tAtt, newStyle);
-			item->itemText.setCharStyle(item->itemText.length()-1, 1, newStyle);
-			lastStyle->StyleStart = item->itemText.length()-1;
+			story.setCharStyle(story.length() - 1, 1, newStyle);
+			lastStyle->StyleStart = story.length() - 1;
 			lastStyle->Style = newStyle;
 		}
 		else if (tName == "nbspace")
 		{
 			CharStyle newStyle;
-			item->itemText.insertChars(item->itemText.length(), SpecialChars::NBSPACE);
+			story.insertChars(story.length(), SpecialChars::NBSPACE);
 			readCharacterStyleAttrs(doc, tAtt, newStyle);
-			item->itemText.setCharStyle(item->itemText.length()-1, 1, newStyle);
-			lastStyle->StyleStart = item->itemText.length()-1;
+			story.setCharStyle(story.length() - 1, 1, newStyle);
+			lastStyle->StyleStart = story.length() - 1;
 			lastStyle->Style = newStyle;
 		}
 		else if (tName == "zwnbspace")
 		{
 			CharStyle newStyle;
-			item->itemText.insertChars(item->itemText.length(), SpecialChars::ZWNBSPACE);
+			story.insertChars(story.length(), SpecialChars::ZWNBSPACE);
 			readCharacterStyleAttrs(doc, tAtt, newStyle);
-			item->itemText.setCharStyle(item->itemText.length()-1, 1, newStyle);
-			lastStyle->StyleStart = item->itemText.length()-1;
+			story.setCharStyle(story.length() - 1, 1, newStyle);
+			lastStyle->StyleStart = story.length() - 1;
 			lastStyle->Style = newStyle;
 		}
 		else if (tName == "zwspace")
 		{
 			CharStyle newStyle;
-			item->itemText.insertChars(item->itemText.length(), SpecialChars::ZWSPACE);
+			story.insertChars(story.length(), SpecialChars::ZWSPACE);
 			readCharacterStyleAttrs(doc, tAtt, newStyle);
-			item->itemText.setCharStyle(item->itemText.length()-1, 1, newStyle);
-			lastStyle->StyleStart = item->itemText.length()-1;
+			story.setCharStyle(story.length() - 1, 1, newStyle);
+			lastStyle->StyleStart = story.length() - 1;
 			lastStyle->Style = newStyle;
 		}
 		else if (tName == "var")
 		{
 			CharStyle newStyle;
 			if (tAtt.value("name") == "pgno")
-				item->itemText.insertChars(item->itemText.length(), SpecialChars::PAGENUMBER);
+				story.insertChars(story.length(), SpecialChars::PAGENUMBER);
 			else
-				item->itemText.insertChars(item->itemText.length(), SpecialChars::PAGECOUNT);
+				story.insertChars(story.length(), SpecialChars::PAGECOUNT);
 			readCharacterStyleAttrs(doc, tAtt, newStyle);
-			item->itemText.setCharStyle(item->itemText.length()-1, 1, newStyle);
-			lastStyle->StyleStart = item->itemText.length()-1;
+			story.setCharStyle(story.length() - 1, 1, newStyle);
+			lastStyle->StyleStart = story.length() - 1;
 			lastStyle->Style = newStyle;
 		}
 
@@ -4781,7 +4973,7 @@
 					else
 					{
 						mark = m_Doc->newMark(oldMark);
-						getUniqueName(l,doc->marksLabelsList(t), "_");
+						getUniqueName(l, doc->marksLabelsList(t), "_");
 					}
 					mark->label = l;
 					if (t == MARKNoteMasterType)
@@ -4804,10 +4996,10 @@
 				if (t == MARKAnchorType)
 					mark->setItemPtr(item);
 				mark->OwnPage = item->OwnPage;
-				item->itemText.insertMark(mark, item->itemText.length());
+				story.insertMark(mark, story.length());
 				readCharacterStyleAttrs(doc, tAtt, newStyle);
-				item->itemText.setCharStyle(item->itemText.length() - 1, 1, newStyle);
-				lastStyle->StyleStart = item->itemText.length() - 1;
+				story.setCharStyle(story.length() - 1, 1, newStyle);
+				lastStyle->StyleStart = story.length() - 1;
 				lastStyle->Style = newStyle;
 			}
 		}
@@ -4817,11 +5009,11 @@
 	return !reader.hasError();
 }
 
-bool Scribus150Format::readItemText(PageItem *obj, ScXmlStreamAttributes& attrs, LastStyles* last)
+bool Scribus150Format::readItemText(StoryText& story, ScXmlStreamAttributes& attrs, LastStyles* last)
 {
 	QString tmp2;
 	CharStyle newStyle;
-	ScribusDoc* doc = obj->doc();
+	ScribusDoc* doc = story.doc();
 	
 	readCharacterStyleAttrs(doc, attrs, newStyle);
 
@@ -4848,7 +5040,7 @@
 
 	int iobj = attrs.valueAsInt("COBJ", -1);
 
-	for (int cxx=0; cxx<tmp2.length(); ++cxx)
+	for (int cxx = 0; cxx < tmp2.length(); ++cxx)
 	{
 		QChar ch = tmp2.at(cxx);		
 		{ // Legacy mode
@@ -4858,7 +5050,7 @@
 				ch = SpecialChars::TAB;
 		}
 		
-		int pos = obj->itemText.length();
+		int pos = story.length();
 		if (ch == SpecialChars::OBJECT)
 		{
 			if (LinkID.contains(iobj))
@@ -4866,13 +5058,13 @@
 				if (FrameItems.contains(LinkID[iobj]))
 				{
 					int fIndex = doc->addToInlineFrames(LinkID[iobj]);
-					obj->itemText.insertObject(pos, fIndex);
+					story.insertObject(pos, fIndex);
 				}
 			}
 			else
 			{
 				if (doc->FrameItems.contains(iobj))
-					obj->itemText.insertObject(pos, iobj);
+					story.insertObject(pos, iobj);
 				else
 					qDebug() << QString("scribus150format: invalid inline frame used in text object : %1").arg(iobj);
 			}
@@ -4881,24 +5073,24 @@
 		{
 //			qDebug() << QString("scribus150format: SHYPHEN at %1").arg(pos);
 			// double SHY means user provided SHY, single SHY is automatic one
-			if (obj->itemText.hasFlag(pos-1, ScLayout_HyphenationPossible))
-			{
-				obj->itemText.clearFlag(pos-1, ScLayout_HyphenationPossible);
-				obj->itemText.insertChars(pos, QString(ch));
+			if (story.hasFlag(pos-1, ScLayout_HyphenationPossible))
+			{
+				story.clearFlag(pos-1, ScLayout_HyphenationPossible);
+				story.insertChars(pos, QString(ch));
 			}
 			else
 			{
-				obj->itemText.setFlag(pos-1, ScLayout_HyphenationPossible);
+				story.setFlag(pos-1, ScLayout_HyphenationPossible);
 			}
 		}
 		else {
-			obj->itemText.insertChars(pos, QString(ch));
+			story.insertChars(pos, QString(ch));
 		}
 //		qDebug() << QString("style at %1: %2 ^ %3 = %4 (%5)").arg(pos).arg((uint)newStyle.effects()).arg((uint)last->Style.effects()).arg((uint)(newStyle.effects() ^ last->Style.effects())).arg(newStyle != last->Style);
 		if (newStyle != last->Style) // || (newStyle.effects() ^ last->Style.effects()) == ScStyle_HyphenationPossible) 
 		{  // FIXME StyleFlag operator== ignores hyphen flag
 //			qDebug() << QString("new style at %1: %2 -> %3").arg(pos).arg(last->Style.asString()).arg(newStyle.asString());
-			obj->itemText.setCharStyle(last->StyleStart, pos-last->StyleStart, last->Style);
+			story.setCharStyle(last->StyleStart, pos-last->StyleStart, last->Style);
 			last->Style = newStyle;
 			last->StyleStart = pos;
 		}
@@ -4908,27 +5100,28 @@
 			if (!last->ParaStyle.isEmpty()) {
 				pstyle.setParent( last->ParaStyle );
 			}
-			obj->itemText.applyStyle(pos, pstyle);
-		}
-	}
-
-	obj->itemText.setCharStyle(last->StyleStart, obj->itemText.length()-last->StyleStart, last->Style);
-	last->StyleStart = obj->itemText.length();
+			story.applyStyle(pos, pstyle);
+		}
+	}
+
+	story.setCharStyle(last->StyleStart, story.length()-last->StyleStart, last->Style);
+	last->StyleStart = story.length();
 /*
 	QString dbg("");
-	for (int i=0; i < obj->itemText.length(); ++i)
-	{
-		dbg += obj->itemText.text(i,1);
-		if (obj->itemText.item(i)->effects() & ScStyle_HyphenationPossible)
+	for (int i=0; i < story.length(); ++i)
+	{
+		dbg += story.text(i,1);
+		if (story.item(i)->effects() & ScStyle_HyphenationPossible)
 			dbg += "~";
 	}
-	qDebug("scribus150format: read itemtext %d '%s'", obj->itemText.length(), dbg.latin1());
+	qDebug("scribus150format: read itemtext %d '%s'", story.length(), dbg.latin1());
 	*/
 	ParagraphStyle pstyle;
 
-	if (!last->ParaStyle.isEmpty()) { // Qt4 >= 0) {
-		pstyle.setParent( last->ParaStyle );
-		obj->itemText.applyStyle(obj->itemText.length()-1, pstyle);
+	if (!last->ParaStyle.isEmpty())
+	{
+		pstyle.setParent(last->ParaStyle);
+		story.applyStyle(story.length() - 1, pstyle);
 	}
 
 	return true;
@@ -6117,7 +6310,7 @@
 		else if (reader.name() == "StoryText")
 		{
 			PageItem* newItem = item->cellAt(row, col).textFrame();
-			readStoryText(doc, reader, newItem);
+			readStoryText(doc, reader, newItem->itemText, newItem);
 		}
 		else
 		{

Modified: trunk/Scribus/scribus/plugins/fileloader/scribus150format/scribus150format.h
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=24265&path=/trunk/Scribus/scribus/plugins/fileloader/scribus150format/scribus150format.h
==============================================================================
--- trunk/Scribus/scribus/plugins/fileloader/scribus150format/scribus150format.h	(original)
+++ trunk/Scribus/scribus/plugins/fileloader/scribus150format/scribus150format.h	Fri Nov 20 14:36:20 2020
@@ -42,19 +42,29 @@
 		// Standard plugin implementation
 		Scribus150Format();
 		virtual ~Scribus150Format();
+
 		QString fullTrName() const override;
 		const AboutData* getAboutData() const override;
 		void deleteAboutData(const AboutData* about) const override;
 		void languageChange() override;
+
 		//Not the same as readSLA. This one only reads max 4k of the file for speed.
 		bool fileSupported(QIODevice* file, const QString & fileName=QString()) const override;
 
+		bool storySupported(const QByteArray& storyData) const override;
+
 		bool loadFile(const QString & fileName, const FileFormat & fmt, int flags, int index = 0) override;
 		bool saveFile(const QString & fileName, const FileFormat & fmt) override;
+		
+		bool loadPalette(const QString & fileName) override;
 		bool savePalette(const QString & fileName) override;
+
+		bool loadElements(const QString & data, const QString& fileDir, int toLayer, double Xp_in, double Yp_in, bool loc) override;
 		QString saveElements(double xp, double yp, double wp, double hp, Selection* selection, QByteArray &prevData) override;
-		bool loadPalette(const QString & fileName) override;
-		bool loadElements(const QString & data, const QString& fileDir, int toLayer, double Xp_in, double Yp_in, bool loc) override;
+
+		bool loadStory(const QByteArray& data, StoryText& story, PageItem* item) override;
+		bool saveStory(StoryText& story, PageItem* item, QByteArray& data) override;
+
 		void addToMainWindowMenu(ScribusMainWindow *) override {};
 
 		// Special features - .sla page extraction support
@@ -125,8 +135,8 @@
 		void readNamedCharacterStyleAttrs(ScribusDoc *doc, ScXmlStreamAttributes& attrs, CharStyle & newStyle);
 		bool readDocItemAttributes(ScribusDoc *doc, ScXmlStreamReader& reader);
 		bool readHyphen(ScribusDoc *doc, ScXmlStreamReader& reader);
-		bool readStoryText(ScribusDoc *doc, ScXmlStreamReader& reader, PageItem* item);
-		bool readItemText(PageItem* item, ScXmlStreamAttributes& attrs, LastStyles* last);
+		bool readStoryText(ScribusDoc *doc, ScXmlStreamReader& reader, StoryText& story, PageItem* item);
+		bool readItemText(StoryText& story, ScXmlStreamAttributes& attrs, LastStyles* last);
 		bool readItemTableData(PageItem_Table* item, ScXmlStreamReader& reader, ScribusDoc *doc);
 		bool readItemTableCell(PageItem_Table* item, ScXmlStreamReader& reader, ScribusDoc *doc);
 		bool readLatexInfo(PageItem_LatexFrame* item, ScXmlStreamReader& reader);
@@ -171,10 +181,14 @@
 
 		void writeCheckerProfiles(ScXmlStreamWriter& docu);
 		void writeLineStyles(ScXmlStreamWriter& docu);
+		void writeLineStyles(ScXmlStreamWriter& docu, const QStringList& styleNames);
+		void writeArrowStyles(ScXmlStreamWriter& docu);
 		void writeJavascripts(ScXmlStreamWriter& docu);
 		void writeBookmarks(ScXmlStreamWriter& docu);
 		void writeColors(ScXmlStreamWriter& docu, bool part = false);
+		void writeColors(ScXmlStreamWriter& docu, const QStringList& colorNames);
 		void writeGradients(ScXmlStreamWriter & docu, bool part = false);
+		void writeGradients(ScXmlStreamWriter & docu, const QStringList& gradientNames);
 		void writeHyphenatorLists(ScXmlStreamWriter& docu);
 		void writePStyles(ScXmlStreamWriter& docu);
 		void writeCStyles(ScXmlStreamWriter& docu);
@@ -185,8 +199,8 @@
 		void putNamedCStyle(ScXmlStreamWriter& docu, const CharStyle & style);
 		void putTableStyle(ScXmlStreamWriter& docu, const TableStyle & style);
 		void putCellStyle(ScXmlStreamWriter& docu, const CellStyle & style);
-		void writeStoryText(ScribusDoc *doc, ScXmlStreamWriter&, PageItem* item);
-		void writeITEXTs(ScribusDoc *doc, ScXmlStreamWriter&, PageItem* item);
+		void writeStoryText(ScribusDoc *doc, ScXmlStreamWriter&, StoryText& story, PageItem* item = nullptr);
+		void writeITEXTs(ScribusDoc *doc, ScXmlStreamWriter&, StoryText& story, PageItem* item = nullptr);
 		void writeLayers(ScXmlStreamWriter& docu);
 		void writePrintOptions(ScXmlStreamWriter& docu);
 		void writePdfOptions(ScXmlStreamWriter& docu);

Modified: trunk/Scribus/scribus/plugins/fileloader/scribus150format/scribus150format_save.cpp
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=24265&path=/trunk/Scribus/scribus/plugins/fileloader/scribus150format/scribus150format_save.cpp
==============================================================================
--- trunk/Scribus/scribus/plugins/fileloader/scribus150format/scribus150format_save.cpp	(original)
+++ trunk/Scribus/scribus/plugins/fileloader/scribus150format/scribus150format_save.cpp	Fri Nov 20 14:36:20 2020
@@ -116,7 +116,8 @@
 		writer.writeEndElement();
 	}
 
-	writeLineStyles(writer);
+	writeLineStyles(writer, lists.lineStyleNames());
+	writeArrowStyles(writer);
 
 	// TODO Write used marks
 	// writeMarks(writer);
@@ -155,6 +156,98 @@
 //	writer.writeEndDocument();
 	documentStr.squeeze();
 	return documentStr.trimmed();
+}
+
+bool Scribus150Format::saveStory(StoryText& story, PageItem* item, QByteArray& data)
+{
+	ResourceCollection lists;
+	QList<PageItem*> embeddedFrames;
+
+	QString fileDir = ScPaths::applicationDataDir();
+	QString documentStr;
+	documentStr.reserve(524288);
+
+	story.getNamedResources(lists);
+
+	ScXmlStreamWriter writer(&documentStr);
+	writer.setAutoFormatting(true);
+//	writer.writeStartDocument();
+	writer.writeStartElement("ScribusStory");
+	writer.writeAttribute("Version", QString(VERSION));
+
+	writeColors(writer, lists.colorNames());
+	writeGradients(writer, lists.gradientNames());
+
+	for (int i = 0; i < story.length(); ++i)
+	{
+		QChar chr = story.text(i);
+		if (chr != SpecialChars::OBJECT)
+			continue;
+		if (!story.hasObject(i))
+			continue;
+		PageItem* pi = story.object(i).getPageItem(story.doc());
+		if (pi && !embeddedFrames.contains(pi))
+			embeddedFrames.append(pi);
+	}
+
+	// Write paragraph styles
+	QList<QString>::Iterator it;
+	QList<QString> names = lists.styleNames();
+	QList<int> styleList = m_Doc->getSortedStyleList();
+	for (int i = 0; i < styleList.count(); ++i)
+	{
+		const ParagraphStyle& paragraphStyle = m_Doc->paragraphStyles()[styleList[i]];
+		if (names.contains(paragraphStyle.name()))
+			putPStyle(writer, paragraphStyle, "STYLE");
+	}
+
+	// Write character styles
+	names = lists.charStyleNames();
+	styleList = m_Doc->getSortedCharStyleList();
+	for (int i = 0; i < styleList.count(); ++i)
+	{
+		const CharStyle& charStyle = m_Doc->charStyles()[styleList[i]];
+		if (!names.contains(charStyle.name()))
+			continue;
+		writer.writeStartElement("CHARSTYLE");
+		putNamedCStyle(writer, charStyle);
+		writer.writeEndElement();
+	}
+
+	writeLineStyles(writer, lists.lineStyleNames());
+	writeArrowStyles(writer);
+
+	// TODO Write used marks
+	// writeMarks(writer);
+
+	// Write note styles
+	names = lists.noteStyleNames();
+	writeNotesStyles(writer, names);
+
+	// TODO Write text notes (once marks are also written)
+	// Do not uncomment before otherwise pasting note frame
+	// will trigger a crash
+	/*QList<TextNote*> textNotes;
+	for (int i = 0; i < nfList.count(); ++i)
+	{
+		PageItem_NoteFrame* noteFrame = nfList.at(i);
+		textNotes.append(noteFrame->notesList());
+	}
+	writeNotes(writer, textNotes);*/
+
+	// FIXME: may be used in embedded objects
+	// writePatterns(writer, fileDir, true, selection);
+	if (!embeddedFrames.isEmpty())
+		WriteObjects(m_Doc, writer, fileDir, nullptr, 0, ItemSelectionFrame, &embeddedFrames);
+	writeStoryText(m_Doc, writer, story);
+	writer.writeEndElement();
+//	writer.writeEndDocument();
+	documentStr.squeeze();
+	documentStr = documentStr.trimmed();
+
+	data = documentStr.toUtf8();
+
+	return true;
 }
 
 bool Scribus150Format::savePalette(const QString & fileName)
@@ -437,6 +530,7 @@
 	writeTableStyles(docu);
 	writeCellStyles(docu);
 	writeLineStyles(docu);
+	writeArrowStyles(docu);
 	writeLayers(docu);
 	writePrintOptions(docu);
 	writePdfOptions(docu);
@@ -515,14 +609,25 @@
 
 void Scribus150Format::writeLineStyles(ScXmlStreamWriter& docu) 
 {
-	QHash<QString,multiLine>::Iterator itMU;
-	for (itMU = m_Doc->docLineStyles.begin(); itMU != m_Doc->docLineStyles.end(); ++itMU)
-	{
+	QStringList styleNames = m_Doc->docLineStyles.keys();
+	if (styleNames.isEmpty())
+		return;
+	writeLineStyles(docu, styleNames);
+}
+
+void Scribus150Format::writeLineStyles(ScXmlStreamWriter& docu, const QStringList& styleNames)
+{
+	if (styleNames.isEmpty())
+		return;
+
+	for (auto itMU = m_Doc->docLineStyles.begin(); itMU != m_Doc->docLineStyles.end(); ++itMU)
+	{
+		if (!styleNames.contains(itMU.key()))
+			continue;
 		docu.writeStartElement("MultiLine");
-		docu.writeAttribute("Name",itMU.key());
+		docu.writeAttribute("Name", itMU.key());
 		multiLine ml = itMU.value();
-		multiLine::iterator itMU2;
-		for (itMU2 = ml.begin(); itMU2 != ml.end(); ++itMU2)
+		for (auto itMU2 = ml.cbegin(); itMU2 != ml.cend(); ++itMU2)
 		{
 			docu.writeEmptyElement("SubLine");
 			docu.writeAttribute("Color", itMU2->Color);
@@ -535,27 +640,29 @@
 		}
 		docu.writeEndElement();
 	}
-	QList<ArrowDesc>::Iterator itar;
-	for (itar = m_Doc->arrowStyles().begin(); itar != m_Doc->arrowStyles().end(); ++itar)
-	{
-		if (itar->userArrow)
-		{
-			docu.writeEmptyElement("Arrows");
-			docu.writeAttribute("NumPoints", itar->points.size());
-			QString arp = "";
-			QString tmp, tmpy;
-			double xa, ya;
-			for (int nxx = 0; nxx < itar->points.size(); ++nxx)
-			{
-				itar->points.point(nxx, &xa, &ya);
-				arp += tmp.setNum(xa) + " " + tmpy.setNum(ya) + " ";
-			}
-			docu.writeAttribute("Points", arp);
-			docu.writeAttribute("Name", itar->name);
-		}
-	}
-}
-
+}
+
+void Scribus150Format::writeArrowStyles(ScXmlStreamWriter& docu)
+{
+	const QList<ArrowDesc>& arrowStyles = m_Doc->arrowStyles();
+	for (const ArrowDesc& arrow : arrowStyles)
+	{
+		if (!arrow.userArrow)
+			continue;
+		docu.writeEmptyElement("Arrows");
+		docu.writeAttribute("NumPoints", arrow.points.size());
+		QString arp;
+		QString tmp, tmpy;
+		double xa, ya;
+		for (int nxx = 0; nxx < arrow.points.size(); ++nxx)
+		{
+			arrow.points.point(nxx, &xa, &ya);
+			arp += tmp.setNum(xa) + " " + tmpy.setNum(ya) + " ";
+		}
+		docu.writeAttribute("Points", arp);
+		docu.writeAttribute("Name", arrow.name);
+	}
+}
 
 void Scribus150Format::writeJavascripts(ScXmlStreamWriter & docu) 
 {
@@ -592,17 +699,24 @@
 
 void Scribus150Format::writeColors(ScXmlStreamWriter & docu, bool part) 
 {	
-	ColorList::Iterator itc;
 	ColorList usedColors;
 	if (part)
 		m_Doc->getUsedColors(usedColors);
 	else
 		usedColors = m_Doc->PageColors;
-	for (itc = usedColors.begin(); itc != usedColors.end(); ++itc)
-	{
-		const ScColor& color = m_Doc->PageColors[itc.key()];
+	writeColors(docu, usedColors.keys());
+}
+
+void Scribus150Format::writeColors(ScXmlStreamWriter& docu, const QStringList& colorNames)
+{
+	for (const QString& colorName : colorNames)
+	{
+		if (colorName == CommonStrings::None)
+			continue;
+
+		const ScColor& color = m_Doc->PageColors[colorName];
 		docu.writeEmptyElement("COLOR");
-		docu.writeAttribute("NAME", itc.key());
+		docu.writeAttribute("NAME", colorName);
 		if (color.getColorModel() == colorModelRGB)
 		{
 			double r, g, b;
@@ -646,14 +760,19 @@
 		m_Doc->getUsedGradients(gradMap);
 	else
 		gradMap = m_Doc->docGradients;
-	for (itGrad = gradMap.begin(); itGrad != gradMap.end(); ++itGrad)
-	{
+	writeGradients(docu, gradMap.keys());
+}
+
+void Scribus150Format::writeGradients(ScXmlStreamWriter & docu, const QStringList& gradientNames)
+{
+	for (const QString& gradientName : gradientNames)
+	{
+		VGradient gradient = m_Doc->docGradients[gradientName];
 		docu.writeStartElement("Gradient");
-		docu.writeAttribute("Name",itGrad.key());
-		VGradient gra = itGrad.value();
-		docu.writeAttribute("Ext", gra.repeatMethod());
-		const QList<VColorStop*>& cstops = gra.colorStops();
-		for (int cst = 0; cst < gra.stops(); ++cst)
+		docu.writeAttribute("Name", gradientName);
+		docu.writeAttribute("Ext", gradient.repeatMethod());
+		const QList<VColorStop*>& cstops = gradient.colorStops();
+		for (int cst = 0; cst < gradient.stops(); ++cst)
 		{
 			docu.writeEmptyElement("CSTOP");
 			docu.writeAttribute("RAMP", cstops.at(cst)->rampPoint);
@@ -1669,30 +1788,30 @@
 	}
 } // namespace anon
 
-void Scribus150Format::writeStoryText(ScribusDoc *doc, ScXmlStreamWriter& docu, PageItem* item)
+void Scribus150Format::writeStoryText(ScribusDoc *doc, ScXmlStreamWriter& docu, StoryText& story, PageItem* item)
 {
 	docu.writeStartElement("StoryText");
 
-	const ParagraphStyle& defaultStyle = item->itemText.defaultStyle();
+	const ParagraphStyle& defaultStyle = story.defaultStyle();
 	putPStyle(docu, defaultStyle, "DefaultStyle");
 
-	writeITEXTs(doc, docu, item);
+	writeITEXTs(doc, docu, story, item);
 
 	docu.writeEndElement();
 }
 
-void Scribus150Format::writeITEXTs(ScribusDoc *doc, ScXmlStreamWriter &docu, PageItem* item)
+void Scribus150Format::writeITEXTs(ScribusDoc *doc, ScXmlStreamWriter &docu, StoryText& story, PageItem* item)
 {
 	CharStyle lastStyle;
 	int lastPos = 0;
 	QString tmpnum;
-	int iTLen = item->itemText.length();
-	if (item->isNoteFrame())
+	int iTLen = story.length();
+	if (item && item->isNoteFrame())
 		iTLen = 0;  //used for saving empty endnotes frames, as they will be filled automatically
 	for (int k = 0; k < iTLen; ++k)
 	{
-		const CharStyle& style1(item->itemText.charStyle(k));
-		const QChar ch = item->itemText.text(k);
+		const CharStyle& style1(story.charStyle(k));
+		const QChar ch = story.text(k);
 
 		if (ch == SpecialChars::OBJECT ||
 			ch == SpecialChars::TAB ||
@@ -1716,24 +1835,24 @@
 			{
 				docu.writeEmptyElement("ITEXT");
 				putCStyle(docu, lastStyle);
-				docu.writeAttribute("CH", textWithSoftHyphens(item->itemText, lastPos, k));
+				docu.writeAttribute("CH", textWithSoftHyphens(story, lastPos, k));
 			}
 			lastStyle = style1;
 			lastPos = k;
 		}
 
-		if (ch == SpecialChars::OBJECT && item->itemText.object(k).getPageItem(doc) != nullptr)
+		if (ch == SpecialChars::OBJECT && story.object(k).getPageItem(doc) != nullptr)
 		{
 			// each obj in its own ITEXT for now
 			docu.writeEmptyElement("ITEXT");
 			putCStyle(docu, lastStyle);
 			tmpnum.setNum(ch.unicode());
 			docu.writeAttribute("Unicode", tmpnum);
-			docu.writeAttribute("COBJ", item->itemText.object(k).getInlineCharID());
-		}
-		else if (ch == SpecialChars::OBJECT && item->itemText.hasMark(k))
-		{
-			Mark* mark = item->itemText.mark(k);
+			docu.writeAttribute("COBJ", story.object(k).getInlineCharID());
+		}
+		else if (ch == SpecialChars::OBJECT && story.hasMark(k))
+		{
+			Mark* mark = story.mark(k);
 			if (!mark->isType(MARKBullNumType))
 			{ //dont save marks for bullets and numbering
 				docu.writeEmptyElement("MARK");
@@ -1743,7 +1862,7 @@
 			}
 		}
 		else if (ch == SpecialChars::PARSEP)	// stores also the paragraphstyle for preceding chars
-			putPStyle(docu, item->itemText.paragraphStyle(k), "para");
+			putPStyle(docu, story.paragraphStyle(k), "para");
 		else if (ch == SpecialChars::TAB)
 		{
 			docu.writeEmptyElement("tab");
@@ -1804,16 +1923,16 @@
 		lastPos = k + 1;
 	}
 	// write pending chars
-	if ( item->itemText.length() - lastPos > 0)
+	if (story.length() - lastPos > 0)
 	{
 		docu.writeEmptyElement("ITEXT");
 		putCStyle(docu, lastStyle);
-		docu.writeAttribute("CH", textWithSoftHyphens(item->itemText, lastPos, item->itemText.length()));
+		docu.writeAttribute("CH", textWithSoftHyphens(story, lastPos, story.length()));
 	}
 	// paragraphstyle for trailing chars
-	if (item->itemText.length() == 0 || item->itemText.text(item->itemText.length()-1) != SpecialChars::PARSEP)
-	{
-		putPStyle(docu, item->itemText.paragraphStyle(item->itemText.length()), "trail");
+	if (story.length() == 0 || story.text(story.length() - 1) != SpecialChars::PARSEP)
+	{
+		putPStyle(docu, story.paragraphStyle(story.length()), "trail");
 	}
 }
 
@@ -2085,7 +2204,7 @@
 				if (item->isNoteFrame())
 					docu.writeAttribute("isNoteFrame", 1);
 				else if (item->isTextFrame() || item->isPathText())
-					writeStoryText(doc, docu, item);
+					writeStoryText(doc, docu, item->itemText, item);
 			}
 		}
 
@@ -2501,7 +2620,7 @@
 					}
 					//End Cell
 					
-					writeStoryText(doc, docu, cell.textFrame());
+					writeStoryText(doc, docu, cell.textFrame()->itemText);
 					docu.writeEndElement();
 				}
 			}

Modified: trunk/Scribus/scribus/sccolor.h
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=24265&path=/trunk/Scribus/scribus/sccolor.h
==============================================================================
--- trunk/Scribus/scribus/sccolor.h	(original)
+++ trunk/Scribus/scribus/sccolor.h	Fri Nov 20 14:36:20 2020
@@ -165,7 +165,7 @@
 	colorModel m_Model {colorModelRGB};
 };
 
-class SCRIBUS_API ColorList : public QMap<QString,ScColor>
+class SCRIBUS_API ColorList : public QMap<QString, ScColor>
 {
 protected:
 	QPointer<ScribusDoc> m_doc;

Modified: trunk/Scribus/scribus/scribus.cpp
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=24265&path=/trunk/Scribus/scribus/scribus.cpp
==============================================================================
--- trunk/Scribus/scribus/scribus.cpp	(original)
+++ trunk/Scribus/scribus/scribus.cpp	Fri Nov 20 14:36:20 2020
@@ -155,6 +155,7 @@
 #include "scribuswin.h"
 #include "selection.h"
 #include "serializer.h"
+#include "storyloader.h"
 #include "styleoptions.h"
 #include "tocgenerator.h"
 #include "ui/about.h"
@@ -4492,16 +4493,16 @@
 			StoryText itemText(doc);
 			itemText.setDefaultStyle(cItem->itemText.defaultStyle());
 			itemText.insert(0, cItem->itemText, true);
-			std::ostringstream xmlString;
-			SaxXML xmlStream(xmlString);
-			xmlStream.beginDoc();
-			itemText.saxx(xmlStream, "SCRIBUSTEXT");
-			xmlStream.endDoc();
-			std::string xml(xmlString.str());
-			ScTextMimeData* mimeData = new ScTextMimeData();
-			mimeData->setScribusText( QByteArray(xml.c_str(), xml.length()) );
-			mimeData->setText( itemText.text(0, itemText.length()) );
-			QApplication::clipboard()->setMimeData(mimeData, QClipboard::Clipboard);
+
+			QByteArray storyData;
+			QScopedPointer<StoryLoader> storyLoader(new StoryLoader());
+			if (storyLoader->saveStory(storyData, *doc, itemText))
+			{
+				ScTextMimeData* mimeData = new ScTextMimeData();
+				mimeData->setScribusText(storyData);
+				mimeData->setText(itemText.text(0, itemText.length()));
+				QApplication::clipboard()->setMimeData(mimeData, QClipboard::Clipboard);
+			}
 		}
 	}
 	else
@@ -4574,43 +4575,38 @@
 		if (currItem->HasSel)
 		{
 			//removing marks and notes from selected text
-//				if (currItem->isTextFrame() && !currItem->asTextFrame()->removeMarksFromText(!ScCore->usingGUI()))
-//					return;
+//			if (currItem->isTextFrame() && !currItem->asTextFrame()->removeMarksFromText(!ScCore->usingGUI()))
+//				return;
 			currItem->deleteSelectedTextFromFrame();
 		}
 
 		if (ScMimeData::clipboardHasScribusText())
 		{
-			Serializer *textSerializer = doc->textSerializer();
-			textSerializer->reset();
-			textSerializer->store<ScribusDoc>("<scribusdoc>", doc);
+			StoryText story(doc);
+			QScopedPointer<StoryLoader> storyLoader(new StoryLoader());
 
 			QByteArray xml = ScMimeData::clipboardScribusText();
-			textSerializer->parseMemory(xml, xml.length());
-
-			StoryText* story = textSerializer->result<StoryText>();
-
-			//avoid pasting notes marks into notes frames
-			if (currItem->isNoteFrame())
+			if (storyLoader->loadStory(xml, *doc, story, currItem))
 			{
-				story->setDoc(doc);
-				for (int pos = story->length() - 1; pos >= 0; --pos)
+				//avoid pasting notes marks into notes frames
+				if (currItem->isNoteFrame())
 				{
-					if (story->hasMark(pos) && (story->mark(pos)->isNoteType()))
-						story->removeChars(pos, 1);
+					for (int pos = story.length() - 1; pos >= 0; --pos)
+					{
+						if (story.hasMark(pos) && (story.mark(pos)->isNoteType()))
+							story.removeChars(pos, 1);
+					}
 				}
+				if (UndoManager::undoEnabled())
+				{
+					ScItemState<StoryText> *is = new ScItemState<StoryText>(Um::Paste);
+					is->set("PASTE_TEXT");
+					is->set("START", currItem->itemText.cursorPosition());
+					is->setItem(story);
+					m_undoManager->action(currItem, is);
+				}
+				currItem->itemText.insert(story);
 			}
-			if (UndoManager::undoEnabled())
-			{
-				ScItemState<StoryText> *is = new ScItemState<StoryText>(Um::Paste);
-				is->set("PASTE_TEXT");
-				is->set("START", currItem->itemText.cursorPosition());
-				is->setItem(*story);
-				m_undoManager->action(currItem, is);
-			}
-			currItem->itemText.insert(*story);
-
-			delete story;
 		}
 		else if (ScMimeData::clipboardHasScribusElem() || ScMimeData::clipboardHasScribusFragment())
 		{

Modified: trunk/Scribus/scribus/scribusdoc.cpp
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=24265&path=/trunk/Scribus/scribus/scribusdoc.cpp
==============================================================================
--- trunk/Scribus/scribus/scribusdoc.cpp	(original)
+++ trunk/Scribus/scribus/scribusdoc.cpp	Fri Nov 20 14:36:20 2020
@@ -3572,6 +3572,26 @@
 	}
 }
 
+ArrowDesc* ScribusDoc::arrowStyle(const QString& name)
+{
+	for (ArrowDesc& arrowDesc : m_docPrefsData.arrowStyles)
+	{
+		if (arrowDesc.name == name)
+			return &arrowDesc;
+	}
+	return nullptr;
+}
+
+bool ScribusDoc::hasArrowStyle(const QString& name) const
+{
+	for (const ArrowDesc& arrowDesc : m_docPrefsData.arrowStyles)
+	{
+		if (arrowDesc.name == name)
+			return true;
+	}
+	return false;
+}
+
 bool ScribusDoc::lineStylesUseColor(const QString& colorName) const
 {
 	bool found = false;

Modified: trunk/Scribus/scribus/scribusdoc.h
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=24265&path=/trunk/Scribus/scribus/scribusdoc.h
==============================================================================
--- trunk/Scribus/scribus/scribusdoc.h	(original)
+++ trunk/Scribus/scribus/scribusdoc.h	Fri Nov 20 14:36:20 2020
@@ -168,39 +168,50 @@
 	void setAutoSaveDir(const QString& autoDaveDir) { m_docPrefsData.docSetupPrefs.AutoSaveDir = autoDaveDir; }
 	//FIXME (maybe) :non const, the loaders make a mess here
 	PDFOptions& pdfOptions() { return m_docPrefsData.pdfPrefs; }
+
 	ObjAttrVector& itemAttributes() { return m_docPrefsData.itemAttrPrefs.defaultItemAttributes; }
 	void setItemAttributes(ObjAttrVector& oav) { m_docPrefsData.itemAttrPrefs.defaultItemAttributes=oav;}
 	void clearItemAttributes() { m_docPrefsData.itemAttrPrefs.defaultItemAttributes.clear(); }
 	void appendToItemAttributes(const ObjectAttribute& oa) { m_docPrefsData.itemAttrPrefs.defaultItemAttributes.append(oa); }
+
 	ToCSetupVector& tocSetups() { return m_docPrefsData.tocPrefs.defaultToCSetups; }
 	void setTocSetups(ToCSetupVector& tsv) { m_docPrefsData.tocPrefs.defaultToCSetups=tsv; }
 	void clearTocSetups() { m_docPrefsData.tocPrefs.defaultToCSetups.clear(); }
 	void appendToTocSetups(const ToCSetup& ts) { m_docPrefsData.tocPrefs.defaultToCSetups.append(ts); }
-	void setArrowStyles(QList<ArrowDesc>& as) { m_docPrefsData.arrowStyles=as; }
+
+	void setArrowStyles(QList<ArrowDesc>& as) { m_docPrefsData.arrowStyles = as; }
 	QList<ArrowDesc>& arrowStyles() { return m_docPrefsData.arrowStyles; }
+	ArrowDesc* arrowStyle(const QString& name);
+	bool hasArrowStyle(const QString& name) const;
 	void appendToArrowStyles(const struct ArrowDesc& as) { m_docPrefsData.arrowStyles.append(as); }
+
 	bool marginColored() const { return m_docPrefsData.displayPrefs.marginColored; }
-	void setMarginColored(bool b) { m_docPrefsData.displayPrefs.marginColored=b; }
+	void setMarginColored(bool b) { m_docPrefsData.displayPrefs.marginColored = b; }
+
 	QMap<QString, CheckerPrefs>& checkerProfiles() { return m_docPrefsData.verifierPrefs.checkerPrefsList; }
-	void setCheckerProfiles(const QMap<QString, CheckerPrefs>& cl) { m_docPrefsData.verifierPrefs.checkerPrefsList=cl; }
+	void setCheckerProfiles(const QMap<QString, CheckerPrefs>& cl) { m_docPrefsData.verifierPrefs.checkerPrefsList = cl; }
 	void set1CheckerProfile(const QString& profileName, const struct CheckerPrefs& cs) { m_docPrefsData.verifierPrefs.checkerPrefsList[profileName] = cs; }
 	void clearCheckerProfiles() { m_docPrefsData.verifierPrefs.checkerPrefsList.clear(); }
 	const QString& curCheckProfile() const { return m_docPrefsData.verifierPrefs.curCheckProfile; }
-	void setCurCheckProfile(const QString& s) { m_docPrefsData.verifierPrefs.curCheckProfile=s; }
+	void setCurCheckProfile(const QString& s) { m_docPrefsData.verifierPrefs.curCheckProfile = s; }
+
 	const QString& language() const { return m_docPrefsData.docSetupPrefs.language; }
-	void setLanguage(const QString& s) { m_docPrefsData.docSetupPrefs.language=s; }
+	void setLanguage(const QString& s) { m_docPrefsData.docSetupPrefs.language = s; }
+
 	int pageOrientation() const { return m_docPrefsData.docSetupPrefs.pageOrientation; }
-	void setPageOrientation(int o) { m_docPrefsData.docSetupPrefs.pageOrientation=o; }
+	void setPageOrientation(int o) { m_docPrefsData.docSetupPrefs.pageOrientation = o; }
 	int pagePositioning() const { return m_docPrefsData.docSetupPrefs.pagePositioning; }
-	void setPagePositioning(int p) { m_docPrefsData.docSetupPrefs.pagePositioning=p; }
+	void setPagePositioning(int p) { m_docPrefsData.docSetupPrefs.pagePositioning = p; }
+
 	double pageHeight() const { return m_docPrefsData.docSetupPrefs.pageHeight; }
 	double pageWidth() const { return m_docPrefsData.docSetupPrefs.pageWidth; }
 	const QString& pageSize() const { return m_docPrefsData.docSetupPrefs.pageSize; }
-	void setPageHeight(double h) { m_docPrefsData.docSetupPrefs.pageHeight=h; }
-	void setPageWidth(double w) { m_docPrefsData.docSetupPrefs.pageWidth=w; }
-	void setPageSize(const QString& s) { m_docPrefsData.docSetupPrefs.pageSize=s; }
+	void setPageHeight(double h) { m_docPrefsData.docSetupPrefs.pageHeight = h; }
+	void setPageWidth(double w) { m_docPrefsData.docSetupPrefs.pageWidth = w; }
+	void setPageSize(const QString& s) { m_docPrefsData.docSetupPrefs.pageSize = s; }
+
 	int marginPreset() const { return m_docPrefsData.docSetupPrefs.marginPreset; }
-	void setMarginPreset(int mp) { m_docPrefsData.docSetupPrefs.marginPreset=mp; }
+	void setMarginPreset(int mp) { m_docPrefsData.docSetupPrefs.marginPreset = mp; }
 
 	TypoPrefs& typographicPrefs() { return m_docPrefsData.typoPrefs; }
 	GuidesPrefs& guidesPrefs() { return m_docPrefsData.guidesPrefs; }
@@ -209,9 +220,9 @@
 	ColorPrefs& colorPrefs() { return m_docPrefsData.colorPrefs; }
 	CMSData& cmsSettings() { return m_docPrefsData.colorPrefs.DCMSset; }
 	DocumentInformation& documentInfo() { return m_docPrefsData.docInfo; }
-	void setDocumentInfo(DocumentInformation di) { m_docPrefsData.docInfo=di; }
+	void setDocumentInfo(DocumentInformation di) { m_docPrefsData.docInfo = di; }
 	DocumentSectionMap& sections() { return m_docPrefsData.docSectionMap; }
-	void setSections(DocumentSectionMap dsm) { m_docPrefsData.docSectionMap=std::move(dsm); }
+	void setSections(DocumentSectionMap dsm) { m_docPrefsData.docSectionMap = std::move(dsm); }
 	const QMap<QString, int> & usedFonts() { return UsedFonts; }
 
 	const ApplicationPrefs& prefsData() { return m_docPrefsData; }

Modified: trunk/Scribus/scribus/scxmlstreamwriter.h
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=24265&path=/trunk/Scribus/scribus/scxmlstreamwriter.h
==============================================================================
--- trunk/Scribus/scribus/scxmlstreamwriter.h	(original)
+++ trunk/Scribus/scribus/scxmlstreamwriter.h	Fri Nov 20 14:36:20 2020
@@ -9,6 +9,7 @@
 
 #include "scribusapi.h"
 
+#include <QByteArray>
 #include <QString>
 #include <QXmlStreamWriter>
 
@@ -16,6 +17,7 @@
 {
 public:
 	ScXmlStreamWriter(void) : QXmlStreamWriter() {}
+	ScXmlStreamWriter(QByteArray* array) : QXmlStreamWriter(array) {}
 	ScXmlStreamWriter(QIODevice* device) : QXmlStreamWriter(device) {}
 	ScXmlStreamWriter(QString*   string) : QXmlStreamWriter(string) {}
 	void writeAttribute(const QString & name, const QString & value) { QXmlStreamWriter::writeAttribute(name, value); }

Modified: trunk/Scribus/scribus/styles/charstyle.cpp
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=24265&path=/trunk/Scribus/scribus/styles/charstyle.cpp
==============================================================================
--- trunk/Scribus/scribus/styles/charstyle.cpp	(original)
+++ trunk/Scribus/scribus/styles/charstyle.cpp	Fri Nov 20 14:36:20 2020
@@ -394,12 +394,25 @@
 
 void CharStyle::getNamedResources(ResourceCollection& lists) const
 {
+	QString colorName;
+
 	for (const BaseStyle* sty = parentStyle(); sty != nullptr; sty = sty->parentStyle())
 		lists.collectCharStyle(sty->name());
-	lists.collectColor(fillColor());
+	
+	const QString& fillColorName = fillColor();
+	if (fillColorName != CommonStrings::None)
+		lists.collectColor(fillColorName);
+
 	lists.collectFontfeatures(fontFeatures());
-	lists.collectColor(strokeColor());
-	lists.collectColor(backColor());
+
+	const QString& strokeColorName = strokeColor();
+	if (strokeColorName != CommonStrings::None)
+		lists.collectColor(strokeColorName);
+
+	const QString& backColorName = backColor();
+	if (backColorName != CommonStrings::None)
+		lists.collectColor(backColorName);
+
 	lists.collectFont(font().scName());
 }
 

Modified: trunk/Scribus/scribus/styles/paragraphstyle.cpp
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=24265&path=/trunk/Scribus/scribus/styles/paragraphstyle.cpp
==============================================================================
--- trunk/Scribus/scribus/styles/paragraphstyle.cpp	(original)
+++ trunk/Scribus/scribus/styles/paragraphstyle.cpp	Fri Nov 20 14:36:20 2020
@@ -236,7 +236,9 @@
 		lists.collectStyle(sty->name());
 	charStyle().getNamedResources(lists);
 
-	lists.collectColor(backgroundColor());
+	const QString& backgroundColorName = backgroundColor();
+	if (backgroundColorName != CommonStrings::None)
+		lists.collectColor(backgroundColorName);
 
 	QString parEffectStyle = peCharStyleName();
 	if (parEffectStyle.length() > 0)

Modified: trunk/Scribus/scribus/text/storytext.cpp
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=24265&path=/trunk/Scribus/scribus/text/storytext.cpp
==============================================================================
--- trunk/Scribus/scribus/text/storytext.cpp	(original)
+++ trunk/Scribus/scribus/text/storytext.cpp	Fri Nov 20 14:36:20 2020
@@ -1538,13 +1538,11 @@
 	invalidate(pos, qMin(i, length()));
 }
 
-
 void StoryText::setStyle(int pos, const ParagraphStyle& style)
 {
 	eraseStyle(pos, paragraphStyle(pos));
 	applyStyle(pos, style);
 }
-
 
 void StoryText::setCharStyle(int pos, uint len, const CharStyle& style)
 {
@@ -1570,8 +1568,6 @@
 	
 	invalidate(pos, pos + len);
 }
-
-
 
 void StoryText::getNamedResources(ResourceCollection& lists) const
 {
@@ -1589,7 +1585,6 @@
 	}
 }
 
-
 void StoryText::replaceStyles(const QMap<QString,QString>& newNameForOld)
 {
 	ResourceCollection newnames;
@@ -1619,7 +1614,6 @@
 	
 	invalidate(0, len);	
 }
-
 
 void StoryText::replaceCharStyles(QMap<QString,QString> newNameForOld)
 {

Modified: trunk/Scribus/scribus/text/storytext.h
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=24265&path=/trunk/Scribus/scribus/text/storytext.h
==============================================================================
--- trunk/Scribus/scribus/text/storytext.h	(original)
+++ trunk/Scribus/scribus/text/storytext.h	Fri Nov 20 14:36:20 2020
@@ -86,6 +86,7 @@
 	void resetMarksCountChanged();
 	
 	void setDoc(ScribusDoc *docin);
+	ScribusDoc* doc() const { return m_doc; }
 	
 	static const Xml_string saxxDefaultElem;
 	static void  desaxeRules(const Xml_string& prefixPattern, desaxe::Digester& ruleset, Xml_string elemtag = saxxDefaultElem);

Modified: trunk/Scribus/win32/msvc2015/scribus-main/Scribus.vcxproj
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=24265&path=/trunk/Scribus/win32/msvc2015/scribus-main/Scribus.vcxproj
==============================================================================
--- trunk/Scribus/win32/msvc2015/scribus-main/Scribus.vcxproj	(original)
+++ trunk/Scribus/win32/msvc2015/scribus-main/Scribus.vcxproj	Fri Nov 20 14:36:20 2020
@@ -353,6 +353,7 @@
     <ClInclude Include="..\..\..\scribus\printpreviewcreator_ps.h" />
     <ClInclude Include="..\..\..\scribus\sccolorstructs.h" />
     <ClInclude Include="..\..\..\scribus\scprintengine_pdf.h" />
+    <moc Include="..\..\..\scribus\storyloader.h" />
     <ClInclude Include="..\..\..\scribus\styles\cellstyle.h" />
     <moc Include="..\..\..\scribus\ui\charselect.h" />
     <moc Include="..\..\..\scribus\ui\charselectenhanced.h" />
@@ -906,6 +907,7 @@
     <ClCompile Include="..\..\..\scribus\sccolorstructs.cpp" />
     <ClCompile Include="..\..\..\scribus\scprintengine_pdf.cpp" />
     <ClCompile Include="..\..\..\scribus\selectionrubberband.cpp" />
+    <ClCompile Include="..\..\..\scribus\storyloader.cpp" />
     <ClCompile Include="..\..\..\scribus\text\boxes.cpp" />
     <ClCompile Include="..\..\..\scribus\text\glyphcluster.cpp" />
     <ClCompile Include="..\..\..\scribus\text\index.cpp" />

Modified: trunk/Scribus/win32/msvc2015/scribus-main/Scribus.vcxproj.filters
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=24265&path=/trunk/Scribus/win32/msvc2015/scribus-main/Scribus.vcxproj.filters
==============================================================================
--- trunk/Scribus/win32/msvc2015/scribus-main/Scribus.vcxproj.filters	(original)
+++ trunk/Scribus/win32/msvc2015/scribus-main/Scribus.vcxproj.filters	Fri Nov 20 14:36:20 2020
@@ -833,6 +833,9 @@
     <ClInclude Include="..\..\..\scribus\text\scworditerator.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="..\..\..\scribus\storyloader.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="..\..\..\scribus\desaxe\digester.cpp">
@@ -2564,6 +2567,9 @@
       <Filter>Source Files</Filter>
     </ClCompile>
     <ClCompile Include="..\..\..\scribus\text\scworditerator.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\..\scribus\storyloader.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
   </ItemGroup>

Modified: trunk/Scribus/win32/msvc2017/scribus-main/Scribus.vcxproj
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=24265&path=/trunk/Scribus/win32/msvc2017/scribus-main/Scribus.vcxproj
==============================================================================
--- trunk/Scribus/win32/msvc2017/scribus-main/Scribus.vcxproj	(original)
+++ trunk/Scribus/win32/msvc2017/scribus-main/Scribus.vcxproj	Fri Nov 20 14:36:20 2020
@@ -353,6 +353,7 @@
     <ClInclude Include="..\..\..\scribus\printpreviewcreator_ps.h" />
     <ClInclude Include="..\..\..\scribus\sccolorstructs.h" />
     <ClInclude Include="..\..\..\scribus\scprintengine_pdf.h" />
+    <moc Include="..\..\..\scribus\storyloader.h" />
     <ClInclude Include="..\..\..\scribus\styles\cellstyle.h" />
     <moc Include="..\..\..\scribus\ui\charselect.h" />
     <moc Include="..\..\..\scribus\ui\charselectenhanced.h" />
@@ -906,6 +907,7 @@
     <ClCompile Include="..\..\..\scribus\sccolorstructs.cpp" />
     <ClCompile Include="..\..\..\scribus\scprintengine_pdf.cpp" />
     <ClCompile Include="..\..\..\scribus\selectionrubberband.cpp" />
+    <ClCompile Include="..\..\..\scribus\storyloader.cpp" />
     <ClCompile Include="..\..\..\scribus\text\boxes.cpp" />
     <ClCompile Include="..\..\..\scribus\text\glyphcluster.cpp" />
     <ClCompile Include="..\..\..\scribus\text\index.cpp" />

Modified: trunk/Scribus/win32/msvc2017/scribus-main/Scribus.vcxproj.filters
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=24265&path=/trunk/Scribus/win32/msvc2017/scribus-main/Scribus.vcxproj.filters
==============================================================================
--- trunk/Scribus/win32/msvc2017/scribus-main/Scribus.vcxproj.filters	(original)
+++ trunk/Scribus/win32/msvc2017/scribus-main/Scribus.vcxproj.filters	Fri Nov 20 14:36:20 2020
@@ -833,6 +833,9 @@
     <ClInclude Include="..\..\..\scribus\text\scworditerator.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="..\..\..\scribus\storyloader.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="..\..\..\scribus\desaxe\digester.cpp">
@@ -2564,6 +2567,9 @@
       <Filter>Source Files</Filter>
     </ClCompile>
     <ClCompile Include="..\..\..\scribus\text\scworditerator.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\..\scribus\storyloader.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
   </ItemGroup>

Modified: trunk/Scribus/win32/msvc2019/scribus-main/Scribus.vcxproj
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=24265&path=/trunk/Scribus/win32/msvc2019/scribus-main/Scribus.vcxproj
==============================================================================
--- trunk/Scribus/win32/msvc2019/scribus-main/Scribus.vcxproj	(original)
+++ trunk/Scribus/win32/msvc2019/scribus-main/Scribus.vcxproj	Fri Nov 20 14:36:20 2020
@@ -354,6 +354,7 @@
     <ClInclude Include="..\..\..\scribus\printpreviewcreator_ps.h" />
     <ClInclude Include="..\..\..\scribus\sccolorstructs.h" />
     <ClInclude Include="..\..\..\scribus\scprintengine_pdf.h" />
+    <moc Include="..\..\..\scribus\storyloader.h" />
     <ClInclude Include="..\..\..\scribus\styles\cellstyle.h" />
     <moc Include="..\..\..\scribus\ui\charselect.h" />
     <moc Include="..\..\..\scribus\ui\charselectenhanced.h" />
@@ -907,6 +908,7 @@
     <ClCompile Include="..\..\..\scribus\sccolorstructs.cpp" />
     <ClCompile Include="..\..\..\scribus\scprintengine_pdf.cpp" />
     <ClCompile Include="..\..\..\scribus\selectionrubberband.cpp" />
+    <ClCompile Include="..\..\..\scribus\storyloader.cpp" />
     <ClCompile Include="..\..\..\scribus\text\boxes.cpp" />
     <ClCompile Include="..\..\..\scribus\text\glyphcluster.cpp" />
     <ClCompile Include="..\..\..\scribus\text\index.cpp" />

Modified: trunk/Scribus/win32/msvc2019/scribus-main/Scribus.vcxproj.filters
URL: http://scribus.net/websvn/diff.php?repname=Scribus&rev=24265&path=/trunk/Scribus/win32/msvc2019/scribus-main/Scribus.vcxproj.filters
==============================================================================
--- trunk/Scribus/win32/msvc2019/scribus-main/Scribus.vcxproj.filters	(original)
+++ trunk/Scribus/win32/msvc2019/scribus-main/Scribus.vcxproj.filters	Fri Nov 20 14:36:20 2020
@@ -833,6 +833,9 @@
     <ClInclude Include="..\..\..\scribus\text\scworditerator.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="..\..\..\scribus\storyloader.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="..\..\..\scribus\desaxe\digester.cpp">
@@ -2564,6 +2567,9 @@
       <Filter>Source Files</Filter>
     </ClCompile>
     <ClCompile Include="..\..\..\scribus\text\scworditerator.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\..\scribus\storyloader.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
   </ItemGroup>




More information about the scribus-commit mailing list