1 /*
2 For general Scribus (>=1.3.2) copyright and licensing information please refer
3 to the COPYING file provided with the program. Following this notice may exist
4 a copyright and/or license notice that predates the release of Scribus 1.3.2
5 for which a new license (GPL+exception) is in place.
6 */
7 #include "textfilter.h"
8 #include <QByteArray>
9 #include <QFile>
10 #include <QFileInfo>
11 #include <QString>
12 #include <QStringList>
13 #include <QTextCodec>
14 #include <QRegExp>
15 #include <QMap>
16 #include <QToolTip>
17 #include "prefsmanager.h"
18 #include "prefsfile.h"
19 #include <vector>
20 #include "gtframestyle.h"
21 #include "gtparagraphstyle.h"
22 #include "tfdia.h"
23 
FileFormatName()24 QString FileFormatName()
25 {
26 	return QObject::tr("Text Filters");
27 }
28 
FileExtensions()29 QStringList FileExtensions()
30 {
31 	return QStringList();
32 }
33 
GetText(const QString & filename,const QString & encoding,bool,gtWriter * writer)34 void GetText(const QString& filename, const QString& encoding, bool, gtWriter *writer)
35 {
36 	TextFilter* tf = new TextFilter(filename, encoding, writer);
37 	delete tf;
38 }
39 
40 /*********** Class TextFilter *************************************/
41 
TextFilter(const QString & fname,const QString & enc,gtWriter * w)42 TextFilter::TextFilter(const QString& fname, const QString& enc, gtWriter* w)
43 {
44 	filename = fname;
45 	encoding = enc;
46 	writer = w;
47 	writer->setOverridePStyleFont(false);
48 	prefs = PrefsManager::instance().prefsFile->getPluginContext("TextFilter");
49 	tfDia* tfdia = new tfDia();
50 	if (tfdia->exec())
51 	{
52 		filters = &(tfdia->filters);
53 		loadText();
54 		write();
55 	}
56 	delete tfdia;
57 }
58 
59 
loadText()60 void TextFilter::loadText()
61 {
62 	QByteArray bb;
63 	text = "";
64 	QFile f(filename);
65 	QFileInfo fi(f);
66 	if (!fi.exists())
67 		return;
68 	// read file content
69 	if (f.open(QIODevice::ReadOnly))
70 	{
71 		bb = f.readAll();
72 		f.close();
73 	}
74 	// decode file content
75 	if (bb.size() > 0)
76 	{
77 		QTextCodec *codec;
78 		if (encoding.isEmpty())
79 			codec = QTextCodec::codecForLocale();
80 		else
81 			codec = QTextCodec::codecForName(encoding.toLocal8Bit());
82 		text = codec->toUnicode(bb);
83 	}
84 }
85 
write()86 void TextFilter::write()
87 {
88 	QMap<QString, gtParagraphStyle*> pstyles;
89 	gtFrameStyle* fstyle = writer->getDefaultStyle();
90 	for (int i = 0; i < static_cast<int>(filters->size()); ++i)
91 	{
92 		if ((*filters)[i]->isEnabled())
93 		{
94 			int action = (*filters)[i]->getAction();
95 			QString regExp = (*filters)[i]->regExp();
96 			QString replaceWith = (*filters)[i]->replaceWith();
97 			bool useRegexp = (*filters)[i]->isRegExp();
98 			if (useRegexp)
99 				replace(&replaceWith);
100 			QString pstyle = (*filters)[i]->getPStyleName();
101 			QRegExp rx = QRegExp(regExp);
102 			rx.setMinimal(true);
103 			switch (action)
104 			{
105 				case REMOVE:
106 					if (useRegexp)
107 						text = text.remove(rx);
108 					else
109 						text = text.remove(regExp);
110 					break;
111 				case REPLACE:
112 					if (useRegexp)
113 						text = text.replace(rx, replaceWith);
114 					else
115 						text = text.replace(regExp, replaceWith);
116 					break;
117 				case APPLY:
118 					pstyles[pstyle] = new gtParagraphStyle(*fstyle);
119 					pstyles[pstyle]->setName(pstyle);
120 					break;
121 			}
122 		}
123 	}
124 	if (pstyles.empty())
125 		writer->append(text);
126 	else
127 	{
128 		QStringList list = text.split("\n", Qt::KeepEmptyParts);
129 		gtParagraphStyle *useStyle = nullptr;
130 		for (int i = 0; i < static_cast<int>(list.size()); ++i)
131 		{
132 			QString tmpText(list[i]);
133 			QString tmpText2(tmpText);
134 			tmpText2 = tmpText2.simplified();
135 			int numberOfWords = tmpText2.count(" ");
136 			++numberOfWords;
137 			useStyle = nullptr;
138 			for (int j = 0; j < static_cast<int>(filters->size()); ++j)
139 			{
140 				if ((*filters)[j]->isEnabled())
141 				{
142 					int action = (*filters)[j]->getAction();
143 					QString regExp = (*filters)[j]->regExp();
144 					QString replaceWith = (*filters)[j]->replaceWith();
145 					bool useRegexp = (*filters)[j]->isRegExp();
146 					if (useRegexp)
147 						replace(&replaceWith);
148 					QString pstyle = (*filters)[j]->getPStyleName();
149 					int lessThan = (*filters)[j]->getLessThan();
150 					int moreThan = (*filters)[j]->getMoreThan();
151 					int style = (*filters)[j]->getStyle();
152 					bool removeMatch = (*filters)[j]->removeMatch();
153 					QRegExp rx = QRegExp(regExp);
154 					if (!pstyle.isEmpty())
155 					{
156 						switch (action)
157 						{
158 							case APPLY:
159 								switch (style)
160 								{
161 								case ALL_PARAGRAPHS:
162 									useStyle = pstyles[pstyle];
163 									break;
164 								case STARTS_WITH:
165 									if (useRegexp)
166 									{
167 										if (tmpText2.indexOf(rx) == 0)
168 										{
169 											useStyle = pstyles[pstyle];
170 											if (removeMatch)
171 												tmpText.remove(rx);
172 										}
173 									}
174 									else
175 									{
176 										if (tmpText2.indexOf(regExp) == 0)
177 										{
178 											useStyle = pstyles[pstyle];
179 											if (removeMatch)
180 												tmpText.remove(regExp);
181 										}
182 									}
183 									break;
184 								case LESS_THAN:
185 									if ((lessThan != -1) && (numberOfWords < lessThan))
186 										useStyle = pstyles[pstyle];
187 									break;
188 								case MORE_THAN:
189 									if ((moreThan != -1) && (numberOfWords > moreThan))
190 										useStyle = pstyles[pstyle];
191 									break;
192 								}
193 								break;
194 						}
195 					}
196 				}
197 			}
198 			if (i == static_cast<int>(list.size()) - 1)
199 				writer->append(tmpText, useStyle);
200 			else
201 				writer->append(tmpText + "\n", useStyle);
202 		}
203 	}
204 }
205 
replace(QString * text)206 void TextFilter::replace(QString* text)
207 {
208 	text->replace("\\\\", "__SLASH_HERE__");
209 	text->replace("\\", "\\");
210 	text->replace("__SLASH_HERE__", "\\\\");
211 
212 	text->replace("\\\\t", "__|TABCHAR|__");
213 	text->replace("\\t", "\t");
214 	text->replace("__|TABCHAR|__", "\\t");
215 
216 	text->replace("\\\\n", "__|L-C|__");
217 	text->replace("\\n", "\n");
218 	text->replace("__|L-C|__", "\\n");
219 
220 	text->replace("\\\\f", "__|F-CHAR|__");
221 	text->replace("\\f", "\f");
222 	text->replace("__|F-CHAR|__", "\\f");
223 
224 	text->replace("\\\\r", "__|R-CHAR|__");
225 	text->replace("\\r", "\r");
226 	text->replace("__|R-CHAR|__", "\\r");
227 
228 	text->replace("\\\\v", "__|V-CHAR|__");
229 	text->replace("\\v", "\v");
230 	text->replace("__|V-CHAR|__", "\\v");
231 
232 	replaceHex(text);
233 }
234 
replaceHex(QString * text)235 void TextFilter::replaceHex(QString* text)
236 {
237 	int index;
238 	int pos = 0;
239 	QString hexS;
240 	int hex;
241 	bool ok = false;
242 	do
243 	{
244 		index = text->indexOf("\\x", pos);
245 		if (index != -1)
246 		{
247 			if ((text->length() - index + 1) > 6)
248 			{
249 				hexS = text->mid(index + 2, 4);
250 				hex = hexS.toInt(&ok, 16);
251 				if (ok)
252 				{
253 					text->replace("\\x" + hexS, QChar(hex));
254 				}
255 			}
256 			else
257 				index = -1;
258 			pos += 2;
259 		}
260 	}
261 	while (index != -1);
262 }
263 
~TextFilter()264 TextFilter::~TextFilter()
265 {
266 
267 }
268