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 /***************************************************************************
8 pageitem.cpp  -  description
9 -------------------
10     begin                : Sat Apr 7 2001
11     copyright            : (C) 2001 by Franz Schmid
12     email                : Franz.Schmid@altmuehlnet.de
13 	***************************************************************************/
14 
15 /***************************************************************************
16 *                                                                         *
17 *   This program is free software; you can redistribute it and/or modify  *
18 *   it under the terms of the GNU General Public License as published by  *
19 *   the Free Software Foundation; either version 2 of the License, or     *
20 *   (at your option) any later version.                                   *
21 *                                                                         *
22 ***************************************************************************/
23 
24 
25 #ifndef STORYTEXT_H_
26 #define STORYTEXT_H_
27 
28 #include <cassert>
29 #include <QObject>
30 #include <QString>
31 #include <QList>
32 #include <unicode/uversion.h>
33 
34 #include "itextsource.h"
35 #include "marks.h"
36 #include "text/frect.h"
37 #include "text/specialchars.h"
38 #include "sctextstruct.h"
39 #include "style.h"
40 #include "styles/charstyle.h"
41 #include "styles/paragraphstyle.h"
42 #include "desaxe/saxio.h"
43 
44 class CharStyle;
45 class ParagraphStyle;
46 class PageItem;
47 class ScribusDoc;
48 class ScText_Shared;
49 class ResourceCollection;
50 class ShapedTextCache;
51 
52 U_NAMESPACE_BEGIN
53 class BreakIterator;
54 U_NAMESPACE_END
55 
56 /**
57  * This class holds the text of a Scribus textframe and pointers to its
58  * styles and embedded objects.
59  *
60  * The logical view of the text consists of a sequence of Unicode chars.
61  * Partition objects keep track of the positions of style changes,
62  * paragraph ends and embedded objects.
63  *
64  * The physical view consists of a sequence of ScriptItems. Each ScriptItem
65  * corresponds to a subsequence of Unicode chars in the original sequence
66  * and associates this with an array of glyph indices. Metrics information
67  * give the physical position of the ScriptItem in the textframe and its
68  * bounding box. For each glyph there's also its advance and the relative
69  * offsets to its basepoint. Other information in the ScriptItem is only
70  * used by the layouter.
71  */
72 class SCRIBUS_API StoryText : public QObject, public SaxIO, public ITextSource
73 {
74 	Q_OBJECT
75 
76 public:
77 	StoryText(ScribusDoc *doc);
78 	StoryText();
79 	StoryText(const StoryText & other);
80 	StoryText& operator= (const StoryText & other);
81 	virtual ~StoryText();
82 
83 	bool hasBulletOrNum() const;
84 	bool hasTextMarks() const;
85 	bool marksCountChanged() const;
86 	void resetMarksCountChanged();
87 
88 	void setDoc(ScribusDoc *docin);
doc()89 	ScribusDoc* doc() const { return m_doc; }
90 
91 	static const Xml_string saxxDefaultElem;
92 	static void  desaxeRules(const Xml_string& prefixPattern, desaxe::Digester& ruleset, Xml_string elemtag = saxxDefaultElem);
93 
94 	virtual void saxx(SaxHandler& handler, const Xml_string& elemtag) const;
saxx(SaxHandler & handler)95 	virtual void saxx(SaxHandler& handler)                     const { saxx(handler, saxxDefaultElem); }
96 
97 	int  cursorPosition() const;
98 	void setCursorPosition(int pos, bool relative = false);
99 	void normalizeCursorPosition();
100 	int  normalizedCursorPosition();
101 
102 	void moveCursorForward();
103 	void moveCursorBackward();
104 	void moveCursorLeft();
105 	void moveCursorRight();
106 
107 	void moveCursorWordLeft();
108 	void moveCursorWordRight();
109 
110 	void clear();
111 	StoryText copy() const;
112 
113 	// Find text in story
114 	int indexOf(const QString &str, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive, int* pLen = 0) const;
115 	int indexOf(QChar ch, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
116 
117 	// Add, change, replace
118 	// Insert chars from another StoryText object at current cursor position
119 	void insert(const StoryText& other, bool onlySelection = false);
120 	// Insert chars from another StoryText object at specific position
121 	void insert(int pos, const StoryText& other, bool onlySelection = false);
122 	// Append chars from another StoryText object
append(const StoryText & other)123 	void append(const StoryText& other) { insert(length(), other, false); }
124 	// Remove len chars at specific position
125  	void removeChars(int pos, uint len);
126 	// Removes trailing empty paragraphs
127 	void trim();
128 	// Insert chars at current cursor position
129 	void insertChars(const QString& txt, bool applyNeighbourStyle = false);
130 	// Insert chars ar specific position
131 	void insertChars(int pos, const QString& txt, bool applyNeighbourStyle = false);
132 	// Insert inline object at current cursor position
133 	void insertObject(int obj);
134 	// Insert object at specific position
135 	void insertObject(int pos, int obj);
136 	// Insert mark at cursor or specific position
137 	void insertMark(Mark* mark, int pos = -1);
138 	// Replace a character
139  	void replaceChar(int pos, QChar ch);
140 	// Replace current selection with specified text
141 	void replaceSelection(const QString& newText);
142  	// Replaced a word, and return the difference in length between old and new
143 	int replaceWord(int pos, QString newWord);
144 	void replaceObject(int pos, int obj);
145 
146 	void hyphenateWord(int pos, uint len, const char* hyphens);
147 
148  	// Retrieve length of story text
149  	int length() const;
150 
151 	// Get content at specific position as plain text
152 	// Internal paragraph separator are converted to
153 	// unix new lines for better compatibility with
154 	// text editors
155 	QString plainText() const;
156 
157 	// TextSource methods
158 
159 	virtual bool isBlockStart(int pos) const;
160 	virtual int nextBlockStart(int pos) const;
161 	virtual InlineFrame object(int pos) const;
162 	virtual bool hasExpansionPoint(int pos) const;
163 	virtual ExpansionPoint expansionPoint(int pos) const;
164 
165 	// Get char at current cursor position
166 //	QChar   text() const;
167 	// Get char at specific position
168  	QChar   text(int pos) const;
169 	// Get text with len chars at specific position
170 	QString text(int pos, uint len) const;
171  	// Get sentence at any position within it
172 	QString sentence(int pos, int &posn);
173 	// Get word starting at position
174 	QString word(int pos);
175 
176 	bool hasObject(int pos) const;
177 	PageItem* getItem(int pos) const; // deprecated
178 	int  findMark(const Mark* mrk, int startPos = 0) const;
179 	bool hasMark(int pos, const Mark* mrk = nullptr) const;
180 	Mark *mark(int pos) const;
181 	void replaceMark(int pos, Mark* mrk);
182 	void applyMarkCharstyle(Mark* mrk, CharStyle& currStyle) const;
183 
184 	bool isHighSurrogate(int pos) const;
185 	bool isLowSurrogate(int pos) const;
186 
187 	// Get charstyle at current cursor position
188 	const CharStyle& charStyle() const;
189 	// Get charstyle at specific position
190  	const CharStyle& charStyle(int pos) const;
191 	// Get paragraph style at current cursor position
192 	const ParagraphStyle& paragraphStyle() const;
193 	// Get paragraph style at specific position
194 	const ParagraphStyle& paragraphStyle(int pos) const;
195 	const ParagraphStyle& defaultStyle() const;
196 	void setDefaultStyle(const ParagraphStyle& style);
197 	void setCharStyle(int pos, uint len, const CharStyle& style);
198 	void setStyle(int pos, const ParagraphStyle& style);
199 	void applyCharStyle(int pos, uint len, const CharStyle& style);
200 	void applyStyle(int pos, const ParagraphStyle& style, bool rmDirectFormatting = false);
201 	void eraseCharStyle(int pos, uint len, const CharStyle& style);
202 	void eraseStyle(int pos, const ParagraphStyle& style);
203 	void replaceStyles(const QMap<QString,QString>& newNameForOld);
204 	void replaceCharStyles(QMap<QString,QString> newNameForOld);
205 
206 	// Cleanup legacy formatting for whole story, ie remove direct
207 	// formatting for parameters already set at paragraph level
208 	void fixLegacyFormatting();
209 
210 	// Cleanup legacy formatting for paragraph at position pos
211 	void fixLegacyFormatting(int pos);
212 
213 	void getNamedResources(ResourceCollection& lists) const;
214 	void replaceNamedResources(ResourceCollection& newNames);
215 
216 	uint nrOfParagraphs() const;
217 	int startOfParagraph() const;
218 	int startOfParagraph(uint index) const;
219 	int endOfParagraph() const;
220 	int endOfParagraph(uint index) const;
221 	uint nrOfParagraph() const;
222 	uint nrOfParagraph(int pos) const;
223 
224 	uint nrOfRuns() const;
225 	int startOfRun(uint index) const;
226 	int endOfRun(uint index) const;
227 
228 // positioning
229 	int nextChar(int pos);
230 	int prevChar(int pos);
231 	int firstWord();
232 	int nextWord(int pos);
233 	int prevWord(int pos);
234 	int endOfWord(int pos) const;
235 	int nextSentence(int pos);
236 	int prevSentence(int pos);
237 	int endOfSentence(int pos) const;
238 	int nextParagraph(int pos);
239 	int prevParagraph(int pos);
240 
241 // these need valid layout:
242 
243 //	int startOfLine(int pos);
244 //	int endOfLine(int pos);
245 //	int prevLine(int pos);
246 //	int nextLine(int pos);
247 //	int startOfFrame(int pos);
248 //	int endOfFrame(int pos);
249 
250 // selection
251 
252 	void selectAll();
253 	void deselectAll();
254 	void removeSelection();
255 	void extendSelection(int oldPos, int newPos);
256 	int selectWord(int pos);
257 	void select(int pos, int len, bool on = true);
258 	QString selectedText() const;
259 	bool selected(int pos) const;
260 	int startOfSelection() const;
261 	int endOfSelection() const;
262 	int selectionLength() const;
263 	bool hasSelection() const;
264 
265 	// break iterators
266 	static icu::BreakIterator* getGraphemeIterator();
267 	static icu::BreakIterator* getWordIterator();
268 	static icu::BreakIterator* getSentenceIterator();
269 	static icu::BreakIterator* getLineIterator();
270 
271 // layout helpers
272 
shapedTextCache()273 	ShapedTextCache* shapedTextCache() { return m_shapedTextCache; }
274 
275 	LayoutFlags flags(int pos) const;
276 	bool hasFlag(int pos, LayoutFlags flag) const;
277 	void setFlag(int pos, LayoutFlags flag);
278 	void clearFlag(int pos, LayoutFlags flag);
279 
280 //  when physical view doesn't match logical view any more:
281 
282 	/// call this if the shape of an embedded object changes (redos layout)
283 	void invalidateObject(const PageItem* embedded);
284 	/// call this if the shape of the paragraph changes (redos layout)
285 	void invalidateLayout();
286 
287 public slots:
288 	/// call this if some logical style changes (redos shaping and layout)
289 	void invalidateAll();
290 
291 signals:
292 	void changed(int firstItem, int endItem);
293 
294 private:
295 	ScText * item(int index);
296 	const ScText * item(int index) const;
297 	void fixSurrogateSelection();
298 
299 private:
300 	ScribusDoc * m_doc;
301 	ShapedTextCache* m_shapedTextCache;
302 	static icu::BreakIterator* m_graphemeIterator;
303 	static icu::BreakIterator* m_wordIterator;
304 	static icu::BreakIterator* m_sentenceIterator;
305 	static icu::BreakIterator* m_lineIterator;
306 
307 	QString textWithSoftHyphens (int pos, uint len) const;
308 	void    insertCharsWithSoftHyphens(int pos, const QString& txt, bool applyNeighbourStyle = false);
309 
310 	/// mark these runs as invalid, ie. need itemize and shaping
311 	void invalidate(int firstRun, int lastRun);
312 	void removeParSep(int pos);
313 	void insertParSep(int pos);
314 
315 	// 	int splitRun(int pos);
316 
317 	/** bring physical view in sync with logical one.
318 	 *  This gets called automatically from all physical view methods
319  	 */
320 // 	void validate();
321 	/// private data structure
322 	ScText_Shared * d;
323 	/// gives the physical view which was last given to the layouter
324 // 	uint layouterVersion;
325  	/// is true after layout() has been exercised
326 // 	bool layouterValid;
327  };
328 
329 
330 #endif /*STORYTEXT_H_*/
331